# 2023 年「資訊科技產業專案設計」作業 1
> [模擬面試錄影-1](https://www.youtube.com/watch?v=U1ojxdzmT9w) (漢) 1. Two Sum
> [模擬面試錄影-2](https://www.youtube.com/watch?v=q3-dDTSpM6I) (漢) 11. Container With Most Water
> [模擬面試錄影-3](https://www.youtube.com/watch?v=A0QBc7ogT9o) (英) 226. Invert Binary Tree
>
> **interviewee** : 😷 郝主意 Goodidea
> **interviewer** : 🎃
## [1. Two Sum](https://leetcode.com/problems/two-sum/)
> `C++`
🎃: 題目是給你一個整數陣列`nums`,以及一個目標整數`target`,請你找出陣列`nums`中哪兩個數字的和會等於目標數字`target`,最後給出這2個數字在`nums`裡的index。 有任何問題可以提出。
> ==不應該直接講題目==。可以帶入某個環境
ex: 有個倉儲公司有一堆不同長度的盒子,某個倉儲任務是要將不同長度的盒子兩兩存放在指定長度的貨櫃內,在只考慮盒子長度的情況下,給定的貨櫃長度,希望你能找到剛好塞入貨櫃的組合以節省空間...之類的。==用引導的方式讓interviewer思考==,這樣才能知道他的想法。
😷: 如果有多個組合的和都等於目標數字是回傳任一一種組合嗎? 🎃: 是的。
😷: 找不到組合或是輸入為空陣列的話就回傳空? 🎃: 是的。
😷: 我舉例一下,若一組輸入是[1,2,3,4,5],目標數字是4的話,我要輸出[0,2],這樣理解對嗎? 🎃: 是的。
😷: 1:42 我初步的想法是用兩個for迴圈去找,第一個for迴圈是找第一個數字,第二個for迴圈是找第二個數字,這樣依序跑下去,把這2個數字加起來。然後去check是不是跟目標數值相等。
用這種方式一直去記錄並更新最大值。同時也要記錄產生最大值的那2個index是多少,最後回傳答案。
```cpp
vector<int> Sum(vector<int>& nums, int target) {
int n = nums.size();
for(int i=0; i<n; i++){
for(j=i+1; j<n; j++){
if (nums[i] + nums[j] == target) {
return {i, j};
}
}
}
return {};
}
```
> 應在自訂函式前先令
`vector<int> nums = {1,2,3,4,5}; `
`int target = 5;` 之類的,讓 interviewer 知道預計 input 的資料型態是什麼。 最後也應對這個vector套用自訂函式,如:`int ans = Sum(nums, target);`
🎃: 你覺得這段程式碼有哪些地方可以改進讓程式碼的運算效率提高?
😷: 目前這段程式碼有2個for迴圈,所以時間複雜度是 $O(n^2)$。如果要提高運算速度的話,我覺得可以從 **第6行** 運算式來改。
```
nums[i] + nums[j] == target
```
😷: 因為在第2個for迴圈裡面,每次在if判斷的時候,都會執行一個加法運算。如果在第一個for迴圈的時候,把這個加法運算改成用`target`減去第一個數值`nums[i]`並記錄他們的差`error`,再進到第2個for迴圈去跟`nums[j]`比較,就可以省下每次在第2個for迴圈裡if的加法運算時間。
```cpp
vector<int> Sum(vector<int>& nums, int target) {
int n = nums.size();
for(int i=0; i<n; i++){
int error = target - nums[i];
for(j=i+1; j<n; j++){
if (nums[j] == error) {
return {i, j};
}
}
}
return {};
}
```
## [11. Container With Most Water](https://leetcode.com/problems/container-with-most-water/)
> `python`
🎃: 題目是給你一個`n`長度的整數陣列`height`,請你在這個陣列裡找出2個高,使得這2個高圍出來的蓄水面積是最大值,最後回傳這個面積最大值是多少。
> ==不應該直接講題目==,可以帶入某個環境:
e.g., 有個水庫工程預計要在山坡建設,事前有評估從上游至下游每個地點的圍牆可建設高度,希望能找到最大的水庫蓄水範圍...之類的。==用引導的方式讓interviewer思考==。
😷: 水位的最高處是由所選的兩個`height`比較短的那條決定? 🎃: 是
🎃: 底是由所選的兩個位置的差值決定? 🎃: 是
😷: 我舉例一下,若輸入是[5,1,2,3,4],因為最大蓄水是頭尾的高而且水位是4,所以輸出4*4=16,這樣理解對嗎? 🎃: 是的。
🎃: 若準備好的話可以開始作答。
😷: 初步的想法是用2個for迴圈決定出2個點。再用這2個位置找值,並更新它的最大值。首先定義一個函式叫做max_area(),它的輸入就是一串陣列。
```python
# python
def max_area(height):
ans = 0
area = 0
for i in range(len(height):
for j in range(i+1,len(height)):
area = min(height[i],height[j]) * (j-i)
if area > ans:
ans = area
return ans
```
> 應在 def 函式前先令一個 array 叫 `height = [5,1,2,3,4]` 之類的,讓 interviewer 知道 input 的資料型態是什麼。 最後也應對這個 array 套用自訂函式,如: `max_area(height)`
🎃: 大概了解你的思路了。你用了2個for迴圈,時間複雜度應該蠻高的。你覺得有什麼方法可以改進它嗎?
😷: 2個for迴圈的時間複雜度是 $O(n^2)$,計算時間會有點久。如果要降低時間複雜度的話,我覺得可以從整個**陣列的兩端下去比較,慢慢往中間去尋找**。選的方式是從兩端比較矮的高度開始往內去尋找。當一邊的高度超越另外一邊的時候,則換另外一邊往內尋找。直到找到最佳解,這樣<font color="#a00">~~時間複雜度只剩 n~~</font>。
>* 6:55 講清楚 $O(n)$,別只講 $n$。
>* 講「從兩端下去找」雖然易懂但有點抽象,可==舉例補充==「分別設定一個index在array的頭和尾」。
```python
# python
def max_area(height):
left = 0
right = len(height-1)
ans = 0
area = 0
while left < right:
area = min(height[i], height[j]) * (j-i)
if area >= ans:
ans = area
if height[left] <= height[right]:
left += 1
else:
right -= 1
return ans
```
🎃: while迴圈內的i跟j是不是有問題?
😷: 我修正一下
> 12:00 打完沒看到bug還被interviewer抓到,==應避免==。
# 沒重新錄影是希望保留錯誤示範,而且這種情況是真的有可能發生。
```python
# python
def max_area(height):
left = 0
right = len(height-1)
ans = 0
area = 0
while left < right:
area = min(height[left], height[right]) * (right-left)
if area >= ans:
ans = area
if height[left] <= height[right]:
left += 1
else:
right -= 1
return ans
```
🎃: 有沒有辦法讓程式碼再更精簡一點?
😷: 原先是左邊或右邊每往內一次就計算一次蓄水面積,如果往內找時高度還比原先小、寬度又沒有比較寬,不可能有更大的面積。因此往內找的時候,找到更大的高度再計算面積就好。
> 這裡interviewee最後打的程式碼沒有更精簡,反而變更長、更醜,但目的是希望提高計算效率。==可以有自己的想法,但要先跟interviewer講,免得答非所問==。
```python
# python
def max_area(height):
left = 0
right = len(height-1)
ans = 0
area = 0
while left < right:
area = min(height[left], height[right]) * (right-left)
if area >= ans:
ans = area
if height[left] <= height[right]:
new_left = left + 1
while (new_left < right) and (height[new_left] < height[left]):
new_left += 1
if new_left == right:
break
else:
left = new_left
else:
new_right = right - 1
while (new_right > left) and (height[new_right] < height[right]):
new_right -= 1
if new_right == left:
break
else :
right = new_right
return ans
```
> 18:09 第17行是打到後來才補上的,有發現邏輯錯誤是好事,==但最好要避免這種情形==,不然可能會讓人覺得interviewee思路不周全。
## 面試過程3(英)---- [226. Invert Binary Tree](https://leetcode.com/problems/invert-binary-tree/)
> `C++`
🎃: Hello Goodidea, welcome to the interview. In today's interview, I will ask you a simple question. **The question is as following. I will give you a root of a binary tree, please invert the tree and return its root。**
> 0:11 不應該直接講題目。可以帶入某個環境,用引導、互動的方式套用這個Leetcode題目。
😷: If the input tree is `NULL`, should I return `NULL`? 🎃: Yes.
😷: Can I use `TreeNode*` as input?
🎃: Yes, of course u can use `TreeNode*` as input and <font color="#a00">~~you need to return a `TreeNode*` as well.~~</font>
> 1:07 針對interviewee的問題回答就好,==不應該跟interviewee講函式要回傳什麼==,感覺像有制式的答案,這樣會限制雙方思考跟互動的空間。
😷: My first thought is to use a recursion function. The **input** is a `TreeNode*`. There're 3 cases in this recursion funtion.
1. " If input is `NULL`, then return `NULL`. ""
1. " If input has no children, then return itself. "
1. " If input has children, then swap them. "
😷: Since it's a recusion funtion, it needs to invert(child_1) and invert(child_2). And finally, return input.
>* 上面說明的input的時候,都是一個`TreeNode*`的root。說明的時候別只講input,==改成講 “ input root ” 會更清楚==。
>* NULL就NULL,不要講成NULL space(不是線代)。
```cpp
Treenode* invert(Treenode* root) {
if (root == NULL) {
return NULL;
}
if ( root ->left == NULL && root->right == NULL) {
return root;
}
else{
Treenode* temp = root->left;
root->left = root->right;
root->right = temp;
}
invert(root->left);
invert(root->right);
return root;
}
```
## 自評
前兩個模擬面試模擬面試錄影用手機錄音的效果有點吵,第三個模擬面試錄影改用耳麥,清楚很多。
#### interviewer
* 三個面試內容都是給一個Leetcode題目,應改用帶入某個環境,用引導互動的方式套用這個題目,以避免看到題目就直接把刷過的Leetcode拿來用。
* 要準備測試用的數據來驗證。
#### interviewee
* 打程式前要先說明預計要用什麼語言寫(C++ or python)。
* 冗言贅字太多,像是:ㄜ..
* 最好測試一下程式碼
---
## HW2-他評01
### interviewer
- [ ] 可改進之處
* [6:48](https://youtu.be/U1ojxdzmT9w?t=408) 在改進方法這邊,時間複雜度也是$O(n^2)$ ,在提問時可以明確指出要降低時間複雜度
### interviewee
- [ ] 優點
* [1:48](https://youtu.be/U1ojxdzmT9w?t=108) 有用肢體語言輔助表達
* [4:26](https://youtu.be/q3-dDTSpM6I?t=266) 詳細描述程式碼
- [ ] 可改進之處
* [1:48](https://youtu.be/U1ojxdzmT9w?t=108) 在說明approach時,如果可以初步給一個程式框架,能讓interviewer更容易理解
* 可以在程式實作完成後,用先前example時所舉的例子做test
## HW2-他評02
### interviewer
- [ ] 優點:
* 口齒清晰
* 題目說明清楚
- [ ] 可改進之處:
* 前面可以在加點自我介紹
* 感覺可以回話有點少缺少一點互動感
### interviewee
- [ ] 優點
* 邊打程式有邊解釋有互動感
* 程式改進的部分非常清楚
## HW2-他評03
### 針對 Interviewer 的檢討:
* 可以包裝一下題目
* 口齒清晰
* 在第一題 Interviewee 優化時,沒有優化到時間複雜度可以引導 Interviewee
* 第三題可以再多一些互動,像是問 Interviewee 覺得Invert Binary Tree 會使用到的場景,有種 Interviewee 還沒火力全開就結束的感覺
### 針對 Interviewee 的檢討:
* 寫完程式碼後可以帶測資去驗證程式碼
* 第二題比較多判斷式的程式碼,建議在實作前和 Interviewer 說明你的程式流程,好處是判斷式一多有時候寫程式碼容易漏掉,若前面有先說明,比較容易發現哪裡漏掉;若這時候有邏輯漏洞,Interviewer 有可能會適當的補充,也能讓 Interviewer 比較容易理解你的程式架構
## HW2-他評04
### Interviewer:
- [ ] 優點
* 題目說明清楚,不只以口頭闡述,也有以文件輔助。
- [ ] 可改進之處
* 題目給法可以不要關鍵字題目名。
* 題目敘述也不要直接給原題,可以換成應用、延伸或者套上情境。
* 最後結尾「大概了解你程式碼的想法了」,之後卻結束了,給人一種尚未了解透徹的感覺,應該可以換個更堅定的語氣,並結束面試。
### Interviewee :
- [ ] 優點
* 舉例有時候是以反白的方式,很棒。
* 有確認例子、有確認作法後得到Interviewer回應才開始。
- [ ] 可改進之處
* 應有測試以滿足 REACTO
## HW2-他評05
### interviewer
- [ ] 優點:
* 聲音清楚
- [ ] 可改進之處:
* 回答問題可以增加互動
### interviewee
- [ ] 優點
* 反覆詢問題意,確認對題目的理解沒有出錯
* 可以邊打程式邊解釋很厲害