# 2023 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2023)」作業 1 > 貢獻者: 真蝦-shrimp > [模擬面試影片-1: 漢語](https://www.youtube.com/watch?v=TN2Vra2AeNU) > [模擬面試影片-2: 漢語](https://www.youtube.com/watch?v=glbXIjHLiEs) > [模擬面試影片: 英語](https://www.youtube.com/watch?v=p9Z23BfNylQ) > > 🧔:interviewer 👶:interviewee ## [206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/) 測驗說明與問答 🧔:你好,我是全聯電子的工程師,很高興能請你來參加這次的coding面試,然後這邊有準備一道題目來做一個程式能力的測驗,我會給你一個linklist,他會由1->2->3,並希望你能reverse整條linklist讓他變成3->2->1又或者5->4->3->2->1變1->2->3->4->5 👶:(作答中) ```c #include <stdio.h> #include <stdlib.h> struct ListNode { int val; struct ListNode *next; }; struct ListNode* reverseList(struct ListNode* head){ if(head == NULL){ return NULL; } if(head -> next == NULL){ return head; } struct ListNode *temp_prev = head; struct ListNode *temp_next = head; struct ListNode *temp_cur = head; temp_next = temp_next -> next; if(temp_next -> next != NULL){ temp_next = temp_next -> next; }else{ temp_next -> next = temp_cur; temp_cur -> next = NULL; head = temp_next; return head; } temp_cur = temp_cur -> next; temp_prev -> next = NULL; temp_cur -> next = temp_prev; temp_prev = temp_cur; temp_cur = temp_next; while(temp_next ->next != NULL){ temp_next = temp_next -> next; temp_cur ->next = temp_prev; temp_prev = temp_cur; temp_cur = temp_next; } temp_cur -> next = temp_prev; head = temp_cur; return head; } ``` 🧔:那你可以分析一下你這樣做的時間複雜度嗎? 👶:我要走完整個list,所以時間會是O(n),而每個for-loop裡面的操作則是O(1),所以整體時間為O(n) 🧔:那像這樣你有沒有考慮用recursive的方式來寫呢 👶:如果用recursive的話我會用以下這樣的寫法(coding) ```c struct ListNode* reverseList(struct ListNode* head) { struct ListNode* ans = head; struct ListNode* prev = NULL; while(head!=NULL){ head = head->next; ans->next = prev; prev = ans; ans = head; } return prev; } ``` 🧔:好那很感謝陳同學你來參加今天的面試,那我們有結果會再通知您 ## [83. Remove Duplicates from Sorted List](https://leetcode.com/problems/remove-duplicates-from-sorted-list/) 測驗說明與問答 🧔:你好,我是這次負責這場面試的工程師,歡迎你來參加我們全聯電子的coding面試,那我今天準備的問題是,有一條linklist會傳給你一個head的pointer那你需要告訴我把中間的重複的點remove掉會長怎樣,現在有兩個例子在這邊給你參考,並且以下會給你一些限制,像是整條list node數會在 O到300之間,而裡面的值會落在-100到100這個範圍,並且會給你一個遞增排序的list,那想問一下你有沒有什麼問題,如果沒有的話就可以開始作答了 👶:(coding中)那這邊就差不多完成了 ```c #include<stdlib.h> #include<stdlib.h> struct ListNode{ int val; struct ListNode *next; }; struct ListNode* deleteDuplicates(struct ListNode* head){ if(head == NULL){ return NULL; } struct ListNode *temp = head; struct ListNode *temp_prev = head; while(temp -> next != NULL){ temp = temp ->next; while(temp_prev -> val == temp -> val){ if(temp ->next == NULL){ temp_prev -> next =NULL; return head; }else{ temp_prev -> next = temp_prev ->next ->next; temp = temp ->next; } } temp_prev = temp_prev ->next; if(temp_prev->next == NULL){ return head; } } return head; } ``` 🧔:那我這邊看你是用兩個pointer來完成這個code,那我希望你用一樣的概念,並且用一個pointer來完成 👶:好,如果改為一個pointer的話來處理的話就是這樣做 ```c struct ListNode* deleteDuplicates(struct ListNode* head) { if(!head) return head; struct ListNode *curr = head; while(curr->next){ if(curr->val == curr->next->val){ struct ListNode *temp = curr->next; curr->next = curr->next->next; free(temp); } else{ curr = curr->next; } } return head; } ``` 🧔:那你可以分析一下你這樣做的時間複雜度嗎? 👶:那這邊要刪除重複節點的話,也是走完整條linklist一次,所以時間會是O(n),而每個for-loop裡面的操作則是O(1),所以整體時間也是O(n) ## [2095. Delete the Middle Node of a Linked List](https://leetcode.com/problems/delete-the-middle-node-of-a-linked-list) 測驗說明與問答 🧔:Welcome to today's interview. I am the engineer responsible for conducting this English interview. Now, you can see that I have a question for you. If there are an even number of nodes in the linked list, delete the ⌊n / 2⌋th node. However, if there is an odd number of nodes, simply delete the middle node. Finally, return the linked list with the middle node removed. 👶:coding ```c #include <stdio.h> #include <stdlib.h> struct ListNode { int val; struct ListNode *next; }; struct ListNode* deleteMiddle(struct ListNode* head){ float count = 0; struct ListNode *temp = (struct ListNode*) malloc(sizeof(struct ListNode)); struct ListNode *targetNode = (struct ListNode*) malloc(sizeof(struct ListNode)); temp ->next = head; while(temp -> next != NULL){ count++; temp = temp ->next; } targetNode -> next = head; if(count == 1){ return NULL; }else{ count = floor(count/2); for(int i = 0; i < count; i++){ targetNode = targetNode -> next; } targetNode ->next = (targetNode ->next) -> next; } return head; } ``` --- ## 他評 - 01 ### 關於 interviewer - [ ] 優點 * 語速穩定,口齒清晰 - [ ] 可改進的地方 * 可以在撰寫程式時提出問題或是多一點問答 ### 關於 interviewee - [ ] 優點 * 撰寫程式時邊講解,方便理解思路 - [ ] 可改進的地方 * [00:48](https://youtu.be/TN2Vra2AeNU?t=48): 缺少 REACTO 的 R、E、A * [8:43](https://youtu.be/TN2Vra2AeNU?t=523): 馬賽克跑掉了 ## 他評 - 02 - [ ] 優點 * 說話清楚、沒有什麼停頓感 * 寫程式時有配合著說明 - [ ] 可改進之處 * [第一題 13:40](https://www.youtube.com/watch?v=TN2Vra2AeNU) Recursive 解法本身沒有問題,但這解法應該不算遞迴,比較算是使用雙重指標的寫法,遞迴應該是函式要呼叫自己本身 ([Wikipedia 定義](https://en.wikipedia.org/wiki/Recursion)) * 比較合理的寫法如下 (參考自 [LeetCode 刷题攻略 - 206.反转链表](https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.md)) ```c ListNode* reverse(ListNode* pre,ListNode* cur){ if(cur == NULL) return pre; ListNode* temp = cur->next; cur->next = pre; return reverse(cur,temp); // 呼叫 reverse() 自己本身 } ListNode* reverseList(ListNode* head) { // 主程式 return reverse(NULL, head); } ``` * [第三題](https://www.youtube.com/watch?v=p9Z23BfNylQ) 後續在 Optimization 的階段,Interviewer 可以再進一步詢問「是否有不用計算 Linked List 長度,但仍可以得到答案之解法?」 * 可以使用雙重指標的寫法,參考自 [Leetcode solution - One Pass - Slow and Fast](https://leetcode.com/problems/delete-the-middle-node-of-a-linked-list/solutions/1612140/one-pass-slow-and-fast/) ```cpp ListNode* deleteMiddle(ListNode* head) { if (head->next == nullptr) return nullptr; auto slow = head, fast = head->next->next; while (fast != nullptr && fast->next != nullptr) { fast = fast->next->next; slow = slow->next; } slow->next = slow->next->next; return head; } ``` - [ ] 其他 * [第二題](https://www.youtube.com/watch?v=glbXIjHLiEs) 沒聲音 :cry: ## 他評03 ### interviewer - [ ] 優點 * 咬字清楚,語速穩定 - [ ] 可改進的地方 * 雙方互動可以增加 * 題目缺少情境 ### interviewee - [ ] 優點 * 分析程式時脈絡完整 - [ ] 可改進的地方 * REACTO不完整 ## 他評04 ### 關於interviewer - [ ] 優點 * 語速適中,咬字清晰。 - [ ] 可改進的地方 * 可以多說明問題細節,舉例讓面試者更了解問題。 * 可以稍微包裝一下題目以防面試者背題目之類的。 ### 關於interviewee - [ ] 優點 * [8:47](https://www.youtube.com/watch?v=TN2Vra2AeNU&t=527s)有註解很棒。 - [ ] 可改進的地方 * [3:36](https://www.youtube.com/watch?v=TN2Vra2AeNU&t=216) 盡量用沒有提示的Editor來打code,例如Notepad或Word。 * [7:07](https://www.youtube.com/watch?v=TN2Vra2AeNU&t=427) else沒有換一行很躁。 :angry: :angry: ## 他評05 ### interviewer - [ ] 優點 * 口條清晰,語速穩定 - [ ] 可改進的地方 * 題目缺少情境 ### interviewee - [ ] 優點 * 可以一邊打程式一邊解說 - [ ] 可改進的地方 * 敲鍵盤聲音有點大 * 影片2沒有聲音