---
tags: info2023-homework1
---
# 2023 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2023)」作業 1
> [模擬面試錄影(漢)](https://youtu.be/sqPCM6ESEZg)
> [模擬面試錄影(漢)](https://youtu.be/-ul6w3t3rgw)
> [模擬面試錄影(英)](https://www.youtube.com/watch?v=QEG4Gdv7aho)
>
> interviewer: :bearded_person:
> interviewee: :monkey_face:
## [101.Symmetric Tree](https://leetcode.com/problems/symmetric-tree/)
> [video](https://youtu.be/sqPCM6ESEZg)
### 題目描述
給定一棵二元樹,檢查它是否是其自身的鏡像(即圍繞其中心對稱)。
```cpp
例如,這個二元樹是對稱的:
1
/ \
2 2
/ \ / \
3 4 4 3
但這個不是:
1
/ \
2 2
\ \
3 3
```
### 程式碼解說
已知樹節點資料結構如下:
```cpp
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode():val(0), left(nullptr), right(nullptr) {}
};
```
#### ***方案一 : Recursion***
```cpp
class Solution {
public:
bool isSymmetric(TreeNode *root) {
if (!root) return true;
return isSymmetric(root->left, root->right);
}
bool isSymmetric(TreeNode *left, TreeNode *right) {
if (!left && !right) return true;
if (left && !right || !left && right || left->val != right->val){
return false;
}
return isSymmetric(left->left, right->right)
&& isSymmetric(left->right, right->left);
}
};
```
最快想到的方法就是用遞迴解決,因為程式碼可讀性高,而且相對容易撰寫。
首先確定根節點是否存在,接著透過遞迴持續比對將所有子節點,直到走訪所有節點。
比對方法左右子樹節點是否一有一無,或者是值不相同。
比對時需注意“左子樹右節點”是和“右子樹左節點”比對,以此類推。
優點:可讀性高,容易撰寫和維護。
缺點:當在binary tree很大時,運行遞迴需維護的stack可能會無法負荷。
時間複雜度最差就是O(n),因為必須要比完所有的節點才知道是否對稱。
#### ***方案二 : Queue***
```cpp
class Solution {
public:
bool isSymmetric(TreeNode* root) {
if (!root) return true;
queue<TreeNode*> q1, q2;
q1.push(root->left);
q2.push(root->right);
while (!q1.empty() && !q2.empty()) {
TreeNode *node1 = q1.front(); q1.pop();
TreeNode *node2 = q2.front(); q2.pop();
if (!node1 && !node2) continue;
if((node1 && !node2) || (!node1 && node2)) return false;
if (node1->val != node2->val) return false;
q1.push(node1->left);
q1.push(node1->right);
q2.push(node2->right);
q2.push(node2->left);
}
return true;
}
};
```
不用遞迴的話,就要自己透過一些資料結構來紀錄節點資訊了。
我選擇用兩個queue來紀錄兩邊的節點,並加以比對。
需注意的是while loop的結束條件是queue為空,與遞迴時不一樣,當子節點皆為nullptr時還是需要繼續比對,因為有可能是左子樹的左子點為空但右子點不同的情形
時間複雜度一樣最差就是O(n),因為必須要比完所有的節點才知道是否對稱。
## [39.Combination Sum](https://leetcode.com/problems/combination-sum)
> [video](https://youtu.be/-ul6w3t3rgw)
### 題目描述
給定一組不重複的候選數字 (candidates)和一個目標數(target),請找出候選數字中加總和達到目標數的所有組合。
其中可以從候選數字中無限次地選擇同個數字。
所有數字(包括目標數)都是正整數。
```cpp
範例:
Input: candidates = [2,3,6,7]
target = 7,
A solution set is:
[
[2,2,3],
[7]
]
```
### 程式碼解說
#### ***方案 : Recursion DFS***
```cpp
class Solution {
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> cur;
std::sort(candidates.begin(), candidates.end());
dfs(candidates, target, 0, cur, ans);
return ans;
}
void dfs(vector<int>& candidates, int target, int s, vector<int>& cur, vector<vector<int>>& ans) {
if (target == 0) {
ans.push_back(cur);
return;
}
for (int i = s; i < candidates.size(); ++i) {
if (candidates[i] > target) break;
cur.push_back(candidates[i]);
dfs(candidates, target - candidates[i], i, cur, ans);
cur.pop_back();
}
}
};
```

用遞迴做深度優先搜尋如上圖,使用cur來紀錄每次搜尋過程,一但符合target,就存到ans中。
而在此之前,可以先排序候選數字 (candidates),這樣搜尋過程中遇到候選數字 (candidates)大於target的情況,就能確保後面的數字都大於target,不用再繼續找下去。且遞迴也可以從最小開始找起。如此一來就能找出所有可能組合解。
## [70.Climbing Stairs](https://leetcode.com/problems/climbing-stairs/)
> [video](https://www.youtube.com/watch?v=QEG4Gdv7aho)
### 題目描述
Imagine you're climbing a staircase with 'n' steps, and you can either climb 1 step or 2 steps at a time. how many different ways can you reach the top?
```cpp
Example:
Input: 2
Output: 2
Explanation: There are two ways to climb to the top.
* 1 step + 1 step
* 2 steps
```
### 程式碼解說
#### ***方案一 : Recursion***
```cpp
int climbStairs(int n) {
if(n==1) return 1;
if(n==2) return 2;
return climbStairs(n-1)+climbStairs(n-2);
}
```
This recursive function will make two recursive calls for each input 'n' except for the base cases when 'n' is 1 or 2.
Therefore, the number of recursive calls grows exponentially with 'n' because each call branches into two more calls.
So The time complexity can be expressed as O($2^n$), where 'n' is the input size (number of steps).
This is a fairly high time complexity and will lead to very high computational costs when the number of stairs is large.
#### ***方案二 : Dynamic Programming***
```cpp
int climbStairs(int n) {
if (n <= 1) return 1;
vector<int> climb_ways(n);
climb_ways[0] = 1;
climb_ways[1] = 2;
for(int i=2; i<n; i++){
climb_ways[i] = climb_ways[i-1]+climb_ways[i-2];
}
return climb_ways[n-1];
}
```
This algorithm uses a for loop to iterate through 'n' steps to calculate the number of ways to reach each step.
In the loop, it performs constant-time operations for each step.
Therefore, the time complexity of this dynamic programming solution is O(n), where 'n' is the input size (number of steps).
# 第二次作業-他評01
## interviewer
### 優點
- 面試過程輕鬆不會太上對下
### 可改進的地方
- 可以將變數限制交給面試者來詢問,一方面看看他是否有在思考邊界條件,另一方便也可以促進溝通
- 面試者的答案都全肯定,建議面試官可以明知故問,給面試者解釋的機會,也可更加理解對面試者的想法
- 建議可以用實際例子來包裝問題
## interviewee
### 優點
- 懂得適時求助面試官給予引導
- 口齒清晰
### 可改進的地方
- 可以把程式碼放在REACTO中的最後一步,coding階段可以先思考最直觀且最暴力的解法,給面試官一個「我可以在短時間內優化」的印象
- repeat(R)階段與example(E)階段同時並行,建議先理解題目意圖再進行舉例
# 第二次作業-他評02
## interviewer
### 優點
- 與 interviewee 的互動很好
- 發問精簡,也有引導 interviewee 優化
### 可改進的地方
- 題目可再做些包裝
## interviewee
### 優點
- 依循 REACTO 流程,有將 Approach 充分討論
- 邊講解例子邊寫出來,讓人容易理解
### 可改進的地方
- 英文解說有點卡卡的
# 第二次作業-他評03
## interviewer
### 優點
- [13:18](https://youtu.be/sqPCM6ESEZg?si=igU6goXCf72nlWEy&t=798):針對程式碼有提供具體的問題,增加討論的空間。
### 可改進的地方
- 若可以用一些生活的例子或是情境來包裝題目會更好。
## interviewee
### 優點
- 整個面試的過程很自然而且很流暢,說明也很清楚。
### 可改進的地方
- [00:56](https://youtu.be/sqPCM6ESEZg?si=7-QywUbm-qumvW0y&t=56):在打例子時我覺得可以稍微說明或是說點話,讓空氣不要太安靜
# 第二次作業-他評04
## interviewer
### 優點
### 可改進的地方
- [14:53](https://youtu.be/QEG4Gdv7aho?si=7506IuDzullVuipj&t=14m53s): 結尾應該要說面試結束之類的客套話。
## interviewee
### 優點
- 解釋方法步驟清楚。
- [8:40](https://youtu.be/-ul6w3t3rgw?si=XTT4ByFhovayfeaJ&t=8m40s): `&`是講專業術語不是and。
### 可改進的地方
- 不應該用有自動補齊的工具。
- 打錯的字有點太多。
- 可以適度反白解釋會更清楚。
- [4:50](https://youtu.be/sqPCM6ESEZg?si=NIbKlNbs6QHyi6l3&t=4m50s): 應該是樹的結構,而且理論上應該要先宣告`struct`再寫主程式。
- [8:25](https://youtu.be/-ul6w3t3rgw?si=XTT4ByFhovayfeaJ&t=8m25s): `start`變數取名為`start_index`或`start_pos`會更清楚,或者在主程式的時候可以先寫註解解釋。
- [13:55](https://youtu.be/-ul6w3t3rgw?si=XTT4ByFhovayfeaJ&t=13m55s): 因為是直接用內建的C++函式,所以是Introsort,排序最佳、平均、最壞時間複雜度都是$O(nlogn)$。
- [13:30](https://youtu.be/QEG4Gdv7aho?si=7506IuDzullVuipj&t=13m30s): 可以將$i<n$的部分反白,會更清楚為何要多一個if的條件判斷。