---
# System prepended metadata

title: 2023 年「資訊科技產業專案設計」作業 1

---

# 2023 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2023)」作業 1
> 貢獻者: 古道梅子-Gudao
> 🐶: Interviewer, 🐱: Interviewee
> [mock interview recording](https://www.youtube.com/watch?v=ia5rzEkO7LM)

## 70. [Climbing Stairs](https://leetcode.com/problems/climbing-stairs/)
### Problem Description
:::warning
You are climbing a staircase. It takes `n` steps to reach the top.

Each time you can either climb `1` or `2` steps. In how many distinct ways can you climb to the top?
:::

### Examples
- Example 1:
    - `n = 3`
        - `(1 1 1)`, `(1 2)`, `(2 1)` (3 ways)
- Example 2:
    - `n = 2`
        - `(1, 1)`, `(2)` (2 ways)

### Solutions
#### Intution 
- Using Recursive
    - base case: `n == 0` or `n == 1`, then return `1`. (because that is the only possible to arrive at the answer)
    - sub-problem:
        - If choose 1 step, then remain `climbstairs(n-1)` to arrive at the answer.
        - If choose 2 step, then remain `climbstairs(n-2)` to arrive at the answer.
    - The answer will be : sum of both sub-problem: `climbstairs(n-1)` + `climbstairs(n-2)`
```cpp
class Solution {
public:
    int climbStairs(int n) {
        if (n == 0 || n == 1) {
        // base case
            return 1;
        }
        return climbStairs(n-1) + climbStairs(n-2);
    }
};
```
:::success
- **Time Complexity: $O(2^n)$** 
- **Space Complexity: $O(n)$**
:::

- 🐢Too slow.... -> Recursive **with memo**.
     - Prevent counting the same sub-problem too many times.
     - If this sub-problem has been counted before, then return it immediately.
```cpp
class Solution {
public:
    int climbStairs(int n, unordered_map<int, int>& memo) {
        if (n == 0 || n == 1) {
            // base case
            return 1;
        }
        if (memo.find(n) == memo.end()) {
            // not find
            memo[n] = climbStairs(n-1, memo) + climbStairs(n-2, memo);
        }
        return memo[n];
    }

    int climbStairs(int n) {
        unordered_map<int, int> memo;
        return climbStairs(n, memo);
    }
};
```

:::success
- **Time Complexity: $O(n)$** 
- **Space Complexity: $O(n)$**
:::
- 🐶: Can you solve this problem by iterative approach?
- Iterative
    - **Bottom-up** to arrive at thet answer.
    - Filling in the DP table by *summing up the values for the previous two steps*.
    - Finally, it returns the value in the last cell of the DP table
```cpp
class Solution {
public:
    int climbStairs(int n) {
        if (n == 0 || n == 1) {
            return 1;
        }

        vector<int> dp(n+1);
        // base case
        dp[0] = dp[1] = 1;
        
        for (int i = 2; i <= n; i++) {
            dp[i] = dp[i-1] + dp[i-2];
        }
        return dp[n];
    }
};
```
:::success
- **Time Complexity: $O(n)$** 
- **Space Complexity: $O(n)$**
:::
- Space Optimization
    - Using only two variables (prev and curr) instead of an entire DP table
```cpp
class Solution {
public:
    int climbStairs(int n) {
        if (n == 0 || n == 1) {
            return 1;
        }
        int prev = 1, curr = 1;
        for (int i = 2; i <= n; i++) {
            int temp = curr;
            curr = prev + curr;
            prev = temp;
        }
        return curr;
    }
};
```

:::success
- **Time Complexity: $O(n)$** 
- **Space Complexity: $O(1)$**
:::


## 1539. [Kth Missing Positive Number](https://leetcode.com/problems/kth-missing-positive-number/description/)
### Description
:::warning
Given an array arr of positive integers sorted in a **strictly increasing order**, and an integer `k`.

Return the `kth` **positive integer** that is **missing** from this array.
:::

### Examples
- Example 1:
    - nums: `[1, 2, 5, 8]`, `k = 2`
        - missing numbers: 3, **4**, 6, 7, 9, 10, 11,...
- Example 2:
    - nums: `[1, 2, 3, 4]`, `k = 2`
        - missing numbers: 5, **6**, 7, 8, 9, 10, 11,...

### Solutions
#### Intution
- Using an integer count that be used to plus 1 everytime.
- Check if the count is in nums or not
    - If count **in** nums: `index = index + 1`
    - If not in nums: `index` do nothing,
```cpp
class Solution {
public:
    int findKthPositive(vector<int>& nums, int k) {
        int count = 1, index = 0;
        int n = nums.size(), total_size = n + k;
        while (count <= total_size) {
            // check if index not out of range and count in nums or not            
            if (index < n && nums[index] == count)
                // find it in nums                 
                index++;
            // not in nums, k need to minus first
            // and check if k is equal to 0 or not.
            // if it's, the answer is count.
            else if (--k == 0) return count;
            count++;
        }
        return count;
    }
};
```
:::success
- **Time Complexity: $O(n+k)$** 
- **Space Complexity: $O(1)$**
:::
- 🐶: Can you solve this problem in less then $O(n+k)$ complexity?
- Thinking:
    - nums: `[1, 2, 5, 8]` (but the counting numbers should be as follows: 1, 2, 3, 4, 5, 6,...)
    - `number of missing positive` in nums are: `[1-1, 2-2, 5-3, 8-4]` = `[0, 0, 2, 4]`
    - So, we need to find the **first index** that **large or equal** than `k`.
    - And the answer will be in range(`nums[index - 1] ~ nums[index]`)
        - The number of missing positive at `index - 1`: 
            - `nums[index - 1] - (index - 1 + 1)` = `nums[index - 1] - index` -----**(eq1.)**
        - The number of missing positive from `index - 1` to `k`:
            - `k` - **(eq1.)** = `k` - (`nums[index - 1] - index`) -----**(eq2.)**
        - The actual kth value starting from `nums[index - 1]`:
            - `nums[index - 1]` - **(eq2.)** = `index + k`
- So, We can using binary search to find the index.
```cpp
class Solution {
public:
    int findKthPositive(vector<int>& nums, int k) {
        int left = 0, right = nums.size();
        while (left < right) {
            int mid = (left + right) / 2;
            if (nums[mid] - mid - 1 < k) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return left + k;
    }
};
```
:::success
- **Time Complexity: $O(logn)$** 
- **Space Complexity: $O(1)$**
:::


## 1838. [Frequency of the Most Frequent Element](https://leetcode.com/problems/frequency-of-the-most-frequent-element/)
### Description
:::warning
The **frequency** of an element is the number of times it occurs in an array.

You are given an integer array `nums` and an integer `k`. In one operation, you can choose an index of `nums` and increment the element at that index by `1`.

Return the maximum possible frequency of an element after performing **at most** `k` operations.
:::

### Examples
- Example 1:
    - nums: `[1, 4, 2]`, `k = 5`
    - nums can become: `[4, 4, 4]`
    - return **3**
- Example 1:
    - nums: `[1, 4, 8, 13]`, `k = 5`
    - nums can become: `[4, 4, 8, 13]`
    - nums can become: `[1, 8, 8, 13]`
    - nums can become: `[1, 4, 13, 13]`
    - return **2**
- Example 1:
    - nums: `[3, 6, 9]`, `k = 2`
    - return **1**


### Solutions
#### Intution
- Sort the input array `nums`.
- For every new element `nums[right]` to the sliding window and add it to `prefix_sum`.
- check if `prefix_sum + k >= nums[right] * sliding window size(right - left + 1)` is vaild that mean we can using less or equal than k times operation to get current window size.
- if not, we need to reduce the window size by move the left index:
    - so, `prefix_sum -= nums[left]`, `left = left + 1`
    - and we need do check this until `prefix_sum + k >= nums[right] * sliding window size(right - left + 1)` become `true`
```cpp
class Solution {
public:
    int maxFrequency(vector<int>& nums, int k) {
        int res = 1, n= nums.size(), left = 0, right;
        long prefix_sum = 0;
        sort(nums.begin(), nums.end());
        for (right = 0; right < n; right++) {
            prefix_sum += A[right];
            while (prefix_sum + k < (long)nums[right] * (right - left + 1)) {
                prefix_sum -= A[left++];
            }
            res = max(res, right - left + 1);
        }
        return res;
    }
};
```

:::success
- **Time Complexity: $O(nlogn)$**, (sorting)
- **Space Complexity: $O(1)$**
:::
- The window can be incorrectly large during some portion of the array; but every time it **expands**, it is **valid**; **otherwise**, it will only **remain its size**, not increase.
- Therefore, it can correctly compute the the largest window size.
- Essentially, we **GROW** the window when it's valid, and **SHIFT** the window when it's invalid.
```cpp
class Solution {
public:
    int maxFrequency(vector<int>& nums, int k) {
        int n= nums.size(), left = 0, right;
        long prefix_sum = 0;
        sort(nums.begin(), nums.end());
        for (right = 0; right < n; right++) {
            prefix_sum += A[right];
            if (prefix_sum + k < (long)nums[right] * (right - left + 1)) {
                prefix_sum -= A[left++];
            }
        }
        return right - left;
    }
};
```
:::success
- **Time Complexity: $O(nlogn)$** 
- **Space Complexity: $O(1)$**
:::

### 自評
- 英文口說需加強
- 雙方缺乏互動
- Interviewer可以嘗試換個情境來說明題目
- 打字速度有點慢
- 提出改進方法後不要馬上實作，要先和interviewer討論
- 可以提出一些問題的運用情境等等
- 面試時記得關掉grammarly

---

## 第二次作業-他評 01 
* 三題影片與筆記幾乎使用全英文, 也都有附上 Optimization, 但少了 Testing, 稍微美中不足. Nevertheless, 可看得出你對自己有一定的要求. 
* [48:20](https://www.youtube.com/watch?v=ia5rzEkO7LM&t=2900s): 陸續開始有雜音干擾. 

### 關於 interviewer 
- [ ] 優點 
* 對於題目描述得很具體，舉例也相當清楚. 
* 我認為你的英文口說不錯. 或許是不習慣邊打字邊說話吧! 

### 關於 interviewee 
- [ ] 優點 
* Approach說明清楚, [1539. Kth Missing Positive Number](https://leetcode.com/problems/kth-missing-positive-number/description/)的 Optimization, 是很精彩的解法.
