# 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, 是很精彩的解法.