# info2023-homework2
> 貢獻者: Huaxin
[21. Merge Two Sorted Lists 模擬面試錄影(漢)](https://youtu.be/cU4FUx7apEY)
## 自評-程式部分
* 很容易在打變數名稱打錯字,需要再細心一點
## 自評-面試過程
* 說話內容,我認為還是有點不流利,我知道這是我的缺點,我會盡可能在生活中去練習。
## 自評-嘗試改進部分
雖然進行了兩次作業,但仍然很緊張,希望能盡快克服這一點
## 他評-嘗試改進部分
感謝大家的指教,我將改進部分整理在下面
1. 英文拼寫要再細心一點
2. 面試官,如果有指定測資可以直接寫在文件中
3. 在敘述 approach 時,可以記錄下幫助理解的文字
4. 沒有說明為何我的方法可以來解決這個問題
5. 在說明快慢指標時,應該加入數學解釋,為何可以找到 middle node
紀錄時間 : 2023/10/14
## [21. Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/description/)
🐕:interviewer 🧑💻:interviewee
🐕:你好,我是今天負責幫你面試的,我們接下來有一套題目要請你解一下,這裡有 4 個 linked list ,請你嘗試進行合併,最後給我合併好的 linked list。
```
list1 = [1,3,5]
list2 = [2,3,7]
list3 = [1,2,3]
list4 = [1,6,17]
```
### repeat
🧑💻:面試官您好,我重申一下您剛剛提的問題,目前有 4 個 linked list,然後進行合併,返回合併好的 linked list,對嗎
🐕:對,這 4 個 linked list 的節點數目範圍落在,0 到 300 個。節點數值範圍為 -200 到 +200
### example
🧑💻:好,那我根據您提供的 linked list ,最後我會得到[1,1,1,2,2,3,3,3,5,6,7,17] 這樣的結果
🐕:沒錯,你的理解是正確的。
### approach
🧑💻:我想先嘗試寫出一個函數,該函數會一次處理 2 個 linked list ,然後我想將 4 個 linked list 先合併成 2 個 linked list ,最後再合併成一個 linked list。
首先對該函數演算法進行說明,他的輸入是 2 個 linked list,我們可以先宣告 2 個指標分別指向 list 的 head,並宣告一個 ptr 指標存放著合併完的節點,接下來我可以定義出幾個狀況,根據這些狀況去依序處理我們的 list,第一個是兩個 list 都存在的情況
* while loop(2 個 list 都存在)
* 如果 list1 的值小於 list2,那就將 list1 的節點放入 ptr 然後 list1 前進一個節點。
* 反之,那就將 list2 的節點放入 ptr 然後 list2 前進一個節點。
第二個情況是接續著第一個情況的,
* while(只有一個 list 存在的話)
* 將該 list 節點放入 ptr 內
🐕:你的想法不錯,那如果節點數目範圍落在 500 至 1000,資料量變大了,你的演算法還能很好的應對嗎。
🧑💻:可以,但是當面對大資料的合併時,所需要的空間複雜度也會隨之增加,而時間複雜度的部分為 O(2*(n+m)),在 4 個變 2 個 linked list 需要 O(2*(n+m)),在 2 變 1 時也需要 O(n+m),總共是 O(3*(n+m))。
🐕:這個想法蠻有意思,你試著寫看看
### code
🧑💻:
```c++=
#include <iostream>
// 定义链表节点结构
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
// 合并两个有序链表的函数
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode dummy(0);
ListNode* curr = &dummy;
// 當兩個 linked list 都存在時
while (list1 && list2) {
if (list1->val < list2->val) { // 較小的節點放入 curr
curr->next = list1;
list1 = list1->next;
} else {
curr->next = list2;
list2 = list2->next;
}
curr = curr->next;
}
// 當只有一個 linked list 存在時
while (list1) {
curr->next = list1;// 把該 linked list 放入 curr
list1 = list1->next;
curr = curr->next;
}
// 當只有一個 linked list 存在時
while (list2) {
curr->next = list2;// 把該 linked list 放入 curr
list2 = list2->next;
curr = curr->next;
}
return dummy.next;
}
int main() {
// 建立 linked list
ListNode* list1 = new ListNode(1);
list1->next = new ListNode(3);
list1->next->next = new ListNode(5);
ListNode* list2 = new ListNode(2);
list2->next = new ListNode(3);
list2->next->next = new ListNode(7);
ListNode* list3 = new ListNode(1);
list3->next = new ListNode(2);
list3->next->next = new ListNode(3);
ListNode* list4 = new ListNode(1);
list4->next = new ListNode(6);
list4->next->next = new ListNode(17);
// 合併 linked list
ListNode* L = mergeTwoLists(list1, list2);
ListNode* R = mergeTwoLists(list3, list4);
ListNode* result = mergeTwoLists(L, R);
// 输出合併后的 linked list
ListNode* current = result;
while (current) {
std::cout << current->val << " -> ";
current = current->next;
}
std::cout << "nullptr" << std::endl;
return 0;
}
```
我們實作合併函數,先宣告一個 dummy 節點,並用一個 curr 指標指向 dummy 節點,當 list1 和 list2 都存在時,我們便去比較兩個 list 的當前節點大小,比較小的那一節點便會由 curr 指標的 next 所指向,接著擁有比較小節點的 list 往下一個節點前進,curr也是。
當剩其中一個 list 存在,我們就進入 while loop ,將該 list 中剩餘的節點轉移至 curr 指標。
然後後續將 linked list 放入函數中,得到兩個 linked list ,再丟入函數中,得當最終的 linked list。
### test
🧑💻:我們舉以下例子做說明
list1 = [1,3,5]
list2 = [2,3,7]
list3 = [1,2,3]
list4 = [1,6,17]
先同時針對 list1 和 list2 以及 list3 和 list4 分別進行合併,以 list1 和 list2 進行說明,當 node 1 和 node 2 比較,node 1 較小,於是便將 node 1 放入 L = [1],後續依此類推可以得到,L = [1,2,3,3,5,7],而 R = [1,1,2,3,6,17],接著再合併一次,得到 result = [1,1,1,2,2,3,3,3,5,6,7,17]
🐕:不錯,那我再考考你,我們這個演算法可以用來解決生活中的什麼問題?
🧑💻:假設公司各部門員工的年終獎金表示成升序的 linked list,我們想要將各部門名單合併並以升序表示。
🐕:這想法挺好的,那面試就到這裡。
## 第四次作業 - 他評01
### Interviewer
- [ ] 優點
- 有針對題目的應用額外提問,很棒
- [ ] 可改進之處
- [0:14](https://youtu.be/cU4FUx7apEY?feature=shared&t=14) 影片中說在 Word 中會提供測資,但畫面中沒看到任何的測資
- [0:28](https://youtu.be/cU4FUx7apEY?feature=shared&t=28) 本課程作業有要求使用台灣科技用語,return 應該說「回傳」而非「返回」
### Interviewee
- [ ] 優點
- 描述演算法很仔細清晰,有同時撰寫虛擬碼協助理解
- 有先針對方法和面試官進行討論再實作,避免實作的方向與面試官的期待不符,很好
- [ ] 可改進之處
- [0:41](https://youtu.be/cU4FUx7apEY?feature=shared&t=42) 應該先說明輸入的資料,而不是直接說輸出的結果,不然螢幕上沒有顯示,也無法判斷是否真的正確
- [4:45](https://youtu.be/cU4FUx7apEY?feature=shared&t=295) 說明時間複雜度時,應該要先說明 $n$ 和 $m$ 分別代表兩個 linked lists 所含的元素個數,再說明時間複雜度為 $O(3\times(n+m))$
- 請想辦法關閉自動句首大寫的功能,或使用不會自動大寫的編輯器來撰寫程式,因為大部分程式語言會視大小寫為不同的 token (case sesitive)