2023 Homework2 === >貢獻者 喬喬 JOJO >Video >[模擬面試影片 (漢)](https://youtu.be/vqFhdXyVXwo) 👨💻:面試官 🧑:面試者 ## [21. Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/description/) 👨💻:第一題是一個關於排程的問題,有兩位學生,他們分別列出他們能跟教授開會的時間並傳給教授,這時教授需要將學生們提出的時間整合,好讓教授能知道有哪些時間是需要騰出來的。 🧑:我重複一下問題,我需要將兩位學生的排程整合,好讓教授能知道哪些時間不可以安排事情? 👨💻:沒錯。 🧑:那我舉個例子,假如兩名學生的排程如下,給教授的排程表最前面的應該是 A 的 1,隨後是 B 的 2,第三個是 B 的 3,以此類推,是這樣嗎?  👨💻:對。 🧑:那如果遇到相同的時間安排,我只將一個時段放入要給教授的排程沒錯吧 👨💻:聽起來符合邏輯。 🧑:那我想到一個方法,首先我們需要定義出排程表的結構,我會定義一個 structure 作為節點,內容包含一個 int 叫 val 用於紀錄時間,在定義一個指標用於指向下一個時間點。再將數個節點串連成 list 來代表行程表,並宣告指標 `tail` 合併行程表的尾端。。 ```c struct ListNode { int val; ListNode *next; }; ListNode *tail; ``` 🧑:接著使用迴圈解決此問題,首先,當兩個行程表皆還有時間沒被放入合併的行程表時,可以從兩個 `list` 當前的開頭比較何者時間較小,放入合併的 `list` ,並記錄放入時間,這時我們可以將合併 `list` 的結尾與剛剛決定出的較小的時間節點相連,並移動 `tail` 使其成為合併 `list` 的新結尾,若當前最小者與記錄的值相同,將其跳過。直到兩個 `list` 其中一個不在具有節點時,將還剩餘時間的 `list` 與回傳 `list` 的 `tail` 相連,最後回傳。 👨💻:感覺都有考慮到,現在請你將他 coding 出來。 ```c ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { ListNode * dummy = new ListNode(); ListNode * tail = dummy ; int record = -1; while( list1 != NULL && list2 != NULL ) { if ( list1->val <= list2->val ) { if (record != list1->val) { tail->next = list1 ; tail = list1 ; record = list1->val; } list1 = list1->next ; } // if else { if (record != list2->val) { tail->next = list2 ; tail = list2 ; record = list2->val; } list2 = list2->next ; } // else } // while if( list1 != NULL ) { if ( record == list1->val) list1 = list1->next; tail->next = list1 ; } else if ( list2 != NULL ) { if ( record == list2->val) list2 = list2->next; tail->next = list2 ; } // else if return dummy->next ; } ``` 👨💻:很好,現在我有一個想法,如果老師本來就有一個排程表,當同學選定的時間點與老師預定課程相同時,就不將其加入要傳給老師的排程表了。 🧑:我會將老師的排程用 hash table 存放,並在原先判斷是否為已加入排成的判別式中增加一個判斷,當當前時間不與老師的時間重複時,才可加入到合併的排程中。 👨💻:請你將改動新增到原先的程式碼中。 ```c ListNode* mergeTwoLists(ListNode* list1, ListNode* list2, ListNode* list3) { unordered_set<int> table; ListNode * walk = list3; while ( walk != NULL) { table.insert(list3->val); walk = walk->next; } ListNode * dummy = new ListNode(); ListNode * tail = dummy ; int record = -1; while( list1 != NULL || list2 != NULL ) { if ( list1->val <= list2->val ) { if (record != list1->val && table.find(list1->val) == table.end()) { tail->next = list1 ; tail = list1 ; record = list1->val; } list1 = list1->next ; } // if else { if (record != list2->val && table.find(list2->val) == table.end()) { tail->next = list2 ; tail = list2 ; record = list2->val; } list2 = list2->next ; } // else } // while while (list1 != NULL) { if ( record != list1->val && table.find(list1->val) == table.end()) { tail->next = list1 ; tail = list1 ; } list1 = list1->next ; } while (list2 != NULL) { if ( record != list2->val && table.find(list2->val) == table.end()) { tail->next = list2 ; tail = list2 ; } list2 = list2->next ; } return dummy->next ; } ``` 👨💻:看起來可行,你能舉的例子來驗證程式碼的正確性嗎? 🧑:好的。 👨💻:那這題的時間複雜度在增加限制條件之後有改變嗎? 🧑:我們可以發現在原先的問題上,我們會將兩個 `list` 都走訪一遍,假設 `list` 長度分別為 n 與 m ,時間複雜度為 $O(n+m)$。而增加限制後對程式碼的影響始有判斷式的條件變多了,所以時間複雜度不變,但可以發現新的問題讓在與剩餘時間排程相連時增加了判別式,需要以 `while` 實現對個別時間的判斷,所以運算時間將會增加。 作業一得到的收穫 === ### 對同學給予建議得到的收穫 #### Interviewer * 可以適當加入背景音樂,讓整體聽感改變。 * 可以將原題經過修飾改成情境題。 * 可以利用**圖**來講解題目,使面試過程更為順暢。 * 在說明題目時可以將文字放大並使用色系差異較大的顏色組合使 interviewee 可以更清楚的看到題目。 * 讀音相近的詞可以用其他語言來代稱,避免聽者被混淆。 * 可以先讓 interviewee 實作提出方法的程式碼再詢問改進方案,讓 interviewee 能先透過 coding 找出當前方法的不足之處,可以更全面的對方法做改進。 * 在 interviewee 完成題目作答後有**引導**答題者精簡程式碼。 #### Interviewee * 注意不要跳過 Repeat 與 Test 這兩個步驟。 * 在與 interviewer 討論時,舉例(Example)應該搭配**畫面**才能使人更好理解,雖然簡單的問題可能並不複雜所以可以讓人很快進入狀況,但要是遇到更複雜的問題可能會導致溝通的效率降低。 * 用圖說明演算法如何執行時,在細節上解釋的不能馬虎,會使讀者不能快速理解講者的作法。 * 在解釋完自己的做法與例子後,可以先與 interviewer 交流,確認此作法合乎雙方的共識再開始 coding。 ### 從同學給予建議得到的收穫 #### Interviewer * 可以多和 interviewee 溝通,不要像問答機器人。 * 講解題目時,可以保留一部份資訊,用於後續溝通。 * 可以再多加討論空間複雜度。 #### Interviewee * 講解時要減少口闢。 * 雜音過於明顯。
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up