# 2023 年「資訊科技產業專案設計」課程第 4 次作業 ## 第 4 次作業-他評 >### 第一位檢討同學: >[月前龍馬-lonmu](https://hackmd.io/@sysprog/B1gGqmzE6) >[video](https://www.youtube.com/watch?v=Ire86ptjVtI) > ### 針對interviewer的檢討 * [0:04](https://youtu.be/Ire86ptjVtI?t=4): 避免講「我有個問題想請你解一下」,可以改成說「首先我們考慮 ___ 的情境」,因為面試的關鍵是溝通,題目只是媒介。 * [0:10](https://youtu.be/Ire86ptjVtI?t=10): 有適度的包裝題目,來避免interviewee直接背題目答案的情形發生。 * [3:35](https://youtu.be/Ire86ptjVtI?t=215): 這邊說「實踐你的想法」,蠻不錯的,因為通常大家都會說「請你開始寫程式碼」,這種說法會讓interviewee感到比較舒服。 * [10:12](https://youtu.be/Ire86ptjVtI?t=612): 說話有點結巴,且最後再說完時間複雜度時,後面有一個類似"呃"的怪聲,可能會讓interviewee沒辦法適度的了解題目,可以盡量避免這種沒有發音好的情況在問問題時發生。 * [11:18](https://youtu.be/Ire86ptjVtI?t=678):說:「需要合併的資料不是只有兩個客戶的話,是多個客戶要一起合併成一個linked list的話。」 * 這邊的"不是"的"不"講得很小聲,容易讓interviewee以為是要合併兩個客戶。在第一句結束時可以省略說"的話",在第一句和第二句中間也可以加上 "而是",來讓題目更容易被intervewee聽懂。 ### 針對interviewee的檢討 * [0:28](https://youtu.be/Ire86ptjVtI?t=28): 有適度的和interviewer溝通,做到repeat & example的步驟,而不是劈頭就直接開始打程式,在確認題意的同時又有跟interviewer互動到,可以讓interviewer留下好印象,讓Interviewer覺得之後和你一起工作是可以和你順利溝通的。 * [5:19](https://youtu.be/Ire86ptjVtI?t=319): 有新增註解,可以幫助自己和interviewer更了解程式撰寫的邏輯,之後再檢查時也可以較快的判斷程式的正確性。 * [7:20](https://youtu.be/Ire86ptjVtI?t=440): 這邊說「我想確認一下我的程式碼有沒有問題」,之後便空出了快30秒的空白時間,這段時間可以再稍微複述一下程式,避免讓interviewer不知道在這段時間不知道要做什麼事。 * [7:52](https://youtu.be/Ire86ptjVtI?t=474): 有確實做到蠻多人都沒有做到的Test的步驟,來驗證程式碼的可執行性,是一個不錯的示範。 * [10:27](https://youtu.be/Ire86ptjVtI?t=616): 這裡頻繁的移動滑鼠以及反白文字,這樣畫面會看起來很雜,也會讓interviewer看的眼花撩亂,盡量避免做出這種不必要的多於動作,來讓interviewer可以專注於interviewe想要表達的內容上。 >### 第二位檢討同學: >[埃默里 Emery](https://hackmd.io/@sysprog/H1snrzfEp#interviewee1) >[video](https://www.youtube.com/watch?v=Ukefw7g95XY) ### 針對interviewer的檢討 * [0:07](https://youtu.be/Ukefw7g95XY?t=7): 開場方式舒服,用 "問題" 取代 "題目",用"討論" 取代 "考" ,這些用詞選擇會讓interviewer跟interviewee在這場面試中,更像是同事在討論公司正在面對的問題,並提出可行的解決方案,比較不像是一種上對下的關係,這樣會讓interviewee在整體的面試體驗上更為良好。 * [0:15](https://youtu.be/Ukefw7g95XY?t=15): 有用包裝的方式來陳述題目,但在google document上卻放了原題的題目,這樣就失去了包裝題目不讓interviewee背答案的用意,google document在一開始還是保持乾淨就好。 * [0:26](https://youtu.be/Ukefw7g95XY?t=26): linked list的發音不太正確,在影片中聽起來像linking list,與實際的發音有出入,可以改善發音方式。 * [7:00](https://youtu.be/Ukefw7g95XY?t=420): 沒有跟interviewee說他剛剛的做法是否為正確,應該要先說他的想法是對的再請他開始實作程式碼。 * [11:17](https://youtu.be/Ukefw7g95XY?t=676):不知道是不是剪輯問題,在interveiwee結束講解後,interviewer應該講話來結束整個面試,講諸如:感謝你今天的時間等等的話語做收尾,但影片中卻沒有出現此段落。 ### 針對interviewee的檢討 * [0:33](https://youtu.be/Ukefw7g95XY?t=33): 有和interviewer確認題目以達到在面試中強調的 "溝通" 效果。 * [1:48](https://youtu.be/Ukefw7g95XY?t=108): 開始寫程式後語速跟打字速度稍慢,如果沒辦法講得很快的話,可以加快打字速度。 * [5:18](https://youtu.be/Ukefw7g95XY?t=318): 有實際測試來驗證這個程式碼的邏輯是否錯誤,這是大多數面試的人容易忽略的過程。 * [10:48](https://youtu.be/Ukefw7g95XY?t=648): 這邊可以等到interviewer題問再講解效率跟空間複雜度,突然開始講解會有點突兀,也減少了跟interviewer溝通的機會。 ## Mock interview ## [21. Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/description/) >[video](https://youtu.be/3Cp4B6qUZYo) >:man_in_tuxedo: : interviewer(parter) :rabbit: : interviewee(me) :man_in_tuxedo: : Hello, You are given the heads of two sorted linked lists list1 and list2. Merge the two lists into one sorted list. The list should be made by splicing together the nodes of the first two lists. Return the head of the merged linked list. :rabbit:: I want to make sure I have correctly understand this question. First, I'll be given two linked list:list1 and list2, and I have to merge this two list to one sorted linked list, is that right? :man_in_tuxedo: : Yes, list1 and list2 will be sorted, so you don't have to worry about the unsorted condition. :rabbit: : OK, I'll give a example: > list1 = [1,3,4] > list2 = [1,2,5] > > output = [1,1,2,3,4,5] :man_in_tuxedo: : Yes. :rabbit: : If it's correct, can I implement my code? :man_in_tuxedo: : you can speak out what you're thinking first. :rabbit: : I'll use recursive method to implement my code. I'll create the function and repeatly call this function to sort these two linked list. :man_in_tuxedo: : OK, go ahead. :rabbit: : ```C++ class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { if(list1 == NULL) return list2; if(list2 == NULL) return list1; if(list1->val < list2->val){ list1->next = mergeTwoLists(list1->next, list2); return list1; } else{ list2->next = mergeTwoLists(list1, list2->next); return list2; } } }; ``` :rabbit: : This is my recursive approach. And I'll use previous example to test my code. First, it'll compare the value of list1 and list2' first value. It'll go to else condition, return list2's value to merge list. So the first value in merge list is 1. Next, pointer'll point to list2' second value:2, and the pointer in list1'll still remain value 1. This code have to compare these two value, 1 and 2. So it'll go to if condition, and return list1's first value:1. And next, first pointer'll point to 3, second pointer'll point to 2. So it'll go to else condition, and return value:2, and so on. The output will be [1,1,2,3,4,5] . :man_in_tuxedo: : You use recursive method to implement your code, but this method cause the problem of stack over flow. In order to avoid this problem, can you use another method to solve this problem? :rabbit: : Instead of using recursive approach, I'll use iterative approach. I'll use while loop to gp through list1 and list2 to merge these two list into the merge linked list. :man_in_tuxedo: : OK, can you implement this method? :rabbit: ```C++ class Solution { public: ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { ListNode* n = new ListNode(0); ListNode* merge = n; while(list1!=NULL && list2!=NULL){ if(list1->val < list2->val){ merge->next = list1; list1 = list1->next; } else{ merge->next = list2; list2 = list2->next; } merge = merge->next; } if(list2 == NULL){ merge->next = list1; } else{ merge->next = list2; } return n->next; } }; ``` :man_in_tuxedo: : OK, so what's the different between these two method? For example the time complexity and space complexity. :rabbit:: I'll first talk about time complexity. In recursive approach, time complexity is O(n+m). :man_in_tuxedo: : Wait, what's n and m? :rabbit: : n is number of value in list1, and m is number of value in list2. So in recursive method it have to go through list1 and list2 to merge these two linked list. Thus, time complexity in recursive method is O(n+m). And in iterative approach, its time complexity is O(n+m), too. Since it'll also go through list1 and list2. :man_in_tuxedo: : O(n+m) is happened in worst case? :rabbit: : Yes, and in space complexity, recursive approach in worst case will be O(n+m). Because list1 and list2 is linked list, it have to store stack states. And in iterative approach, time complexity is O(1). :man_in_tuxedo: : OK, Thanks for you time. Good bye. ## [2295. Replace Elements in an Array](https://leetcode.com/problems/replace-elements-in-an-array/description/) >[video](https://youtu.be/flTUF_zPe4s) **Interviewer:** partner &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; **Interviewee:** me **Interviewer** :ok,so I will ask about the iterative question,and this question is about You are given a 0-indexed array nums that consists of n distinct positive integers. Apply m operations to this array, where in the ith operation you replace the number operations[i][0] with operations[i][1] and you have to return the array obtained after applying all the operations. **Interviewee:** ok,does the first number in the operation must exist in nums? **Interviewer:** yes **Interviewee:** ok ,does the second number in the operation not exist in nums? **Interviewer:** yes,alright **Interviewee:** so it provides the distinct postive integers,right? **Interviewer:** right **Interviewee:** OK so let me repeat the question that you say ,so I have a number list and a numbers of operations and each operation's first number is in the nums array and the second number is the the first number we need to replace by right? so we need to return the modified array is that alright? **Interviewer:** right **Interviewee:** so let me make a example to guarantee the algorithm is right, we given the numbers array that is consist of [1,2,4,6] and the operation is consist of [[1,3],[4,7],[6,1]],so the output answer will be [3,2,7,1],is that correct? **Interviewer:** yes,that's correct **Interviewee:** ok,To implement this problem first come to my mind is use 2 for loop to solve this problem and the outer for loop is for operations ,we need to iterate all the operations and inner for loop is for figure out what is need to be replaced in nums,so I will implement this method ```python! class Solution: def arrayChange(self, nums: List[int], operations: List[List[int]]) -> List[int]: for i in operations: for j in range(len(nums)): if nums[j]==i[0]: nums[j]=i[1] return nums ``` **Interviewer:** OK,can you talk about the the time complexity and space complexity? **Interviewee:** so we first define n is the size of nums and the m is the size of operations and the time complexity of this solution is O(M*N) because we use two for-loop to iterate the nums and operation ,so at most gone through O(M*N) times to solve this problem,and space complexit is constantly time because all the modifies in this solution is in nums array,so we don:t need to use extra space to record the numbers **Interviewer:** OK, but the time complexity is not the optimal solution so can you improve the algorithm using another method? **Interviewee:** OK, I can use dictionary to mapping the operations pairs and use 1 for-loop to iterate all the nums list and in each steps we just need to figure out whether the element is in the operations Dictionary and replace it,so it will cost O(N) to solve problem,is that right? **Interviewer:** but if you use this approach it will be some numbers in nums be replace once if you encounter the situation that you have to iterate the numsfor two times ,this approach might not work,so canyou give another approach? **Interviewee:** so you means if the nums is [1,2,4,6] and the operation will be [[1,3],[3,8]] if I use 1 for -loop to iterate numbers and 1 will only modify once I will miss the second replacement,did you means this? **Interviewer:** yes **Interviewee:** OK, we can change the operation from nums to operations and in each operations,we will need to use dictionary to record the nums's index,so in each step we just need to figure out the first nember in the operations' index abd replacement that index and update the second numbers index and so on,so I will return the nums,is that right? **Interviewer:** yes,this approch is good **Interviewee:** so I will implement this solution ```python! class Solution: def arrayChange(self, nums: List[int], operations: List[List[int]]) -> List[int]: Dict=dict() for i in range(len(nums)): Dict[nums[i]]=i for i in operations: nums[Dict[i[0]]]=i[1] Dict[i[1]]=Dict[i[0]] return nums ``` **Interviewee:** let me test this solution ,given the same example and we first build a dictionary that is equal to{1:0,2:1,4:2,6:3} and we just iterate the operations , in first step numwill become [3,2,4,6] and the dictionary will become {1:0,2:1,4:2,6:3,3,0} in second step numwill become [3,2,7,6] and the dictionary will become {1:0,2:1,4:2,6:3,3,0,7:2} in final step numwill become [3,2,7,1] and the dictionary will become {1:3,2:1,4:2,6:3,3,0,7:2} this answer is equal to the first answer **Interviewer:** OK can you talk about the time complexity and the space complexity in this method? **Interviewee:** OK the the time complexity we first define M is for the size of operations,so the complexity is O(M) because we just need to use 1 for-loop to iterate the whole operations and the space complexity will be O(N) where N is the size of nums array because we need to build dictonary that consist of the numbers of nums so extra space is O(N) **Interviewer:** OK,thanks for your time. ## 檢討這學期的表現 因為還未曾有過實際的面試經驗,所以一開始在做作業時有點不知所措,不太了解實際的面試情況是如何。但透過教授的講課內容與面試技巧介紹,學到了REACTO和各種面試時需要注意小地方,並在之後作業的檢討、教授在課堂上的mock interview後,漸漸能理解在面試時的應對方式和說話的藝術。 我在這堂課上花費了蠻多時間和心思來準備作業和聽教授講課。第一次作業時為了要錄出符合教授要求的影片就花了足足一個禮拜的時間來揣摩和錄製影片,之後的第二、三次作業在檢討同學的影片和撰寫履歷還有找工作職缺上也花了不少工夫,第四次作業算是總體的驗收了第一次作業和第二次作業檢討後的改善成果。在第四次作業基於第一次作業的改善上,我做到了在第一次作業時沒有做到的 "提出更好解法" 和 "驗證程式碼" 的步驟,英文的表達上也較流利。在第四次作業基於第二次作業的改善上我也避免只講心法,而是在看過其他同學錄製的影片後,在影片的時間軸上給予需要改善的實際建議來幫助同學更能實際改善面試過程。 總結來說,我在這堂課上學習到了參與面試的各種技巧和心法,在模擬實際狀況的過程中也意識到了自己的不足並依教授所提供的方法來進行改善,也了解了擔任面試官和面試員的心境及需要注意的事項,收穫滿滿。