# 2023 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2023/https%3A%2F%2Fhackmd.io%2F%40sysprog%2FS11ooE4Rh)」作業 2
>[模擬面試影片(漢)](https://youtu.be/ElSse721QWM)
>🍔:interviewer 🍤:interviewee
## [287. Find the Duplicate Number](https://leetcode.com/problems/find-the-duplicate-number/)
🍔:你好,我是XXX公司的工程師,今天由我來主持這場面試。我們先簡單測試一下你的程式邏輯吧!架設現在有一場藝術品拍賣會,其中,最著名的一幅畫作被稱為「星空之夜」。
然而,在拍賣進行之前,藝術品專家們發現了一個問題。「星空之夜」畫作由於地下組織的干擾,出現了未知數量的複製品,唯一的區別是,這些畫作的拍賣編號相同。
為了確保拍賣的公平性和透明性,拍賣會需要一個方法來識別這些重複的拍賣編號。請問這種情況你會怎麼做呢?
***Repeat***
🍤:好的,您的意思是希望我找出這些編號中重複的編號,請問我的理解正確嗎?
🍔:是的,你的理解沒錯。
***Example***
🍤:好的,在我之前的工作中,我也解決過類似的問題,當時是有不少表單透過人工的方式蒐集,在歸檔的時候同樣出現了重複編號的錯誤。那麼接下來請讓我舉個例子來驗證我的理解是否符合您的需求,我先分享一下螢幕畫面,請稍等。假設現在有一個儲存編號的陣列,其內容是[3,1,3,4,2],我必須要找出重複的那個編號,也就是3;如果陣列內容是[2,1,3,4,2,2],我需要找出2。請問我的理解是否正確?
```python
[3,1,3,4,2] --> 3
[2,1,3,4,2,2] --> 2
```
🍔:是的,你的理解沒錯。
***Approach***
🍤:好的,我大致理解您的需求了。針對這種情況,我選擇使用2個迴圈:
- 外迴圈:使用i控制,依序遍歷整個陣列,array[i]是我們要檢查是否重複的目標
- 內迴圈:使用j控制,j會等於i+1,這樣就不會檢查自己以及檢查過的
🍔:了解,這個方法聽起來可行。
***Coding***
🍤:好的,那我就開始撰寫我的程式碼。我選擇使用Python撰寫。
```python
def findDuplicate(self, nums):
for i in range((len(nums))):
for j in range(i+1,len(nums)):
if nums[i]==nums[j]:
return nums[i]
return -1
```
***Test***
🍤:程式碼到這就完成了,時間複雜度是$O(n^2)$,空間複雜度是$O(1)$。那麼接下來我想測試這個程式的輸出。假設現在所有畫作的編號是[1,2,3,2]。
1. `i==0`, `num[i]==1`
- `j==1`, `num[j]==2`
- `j==2`, `num[j]==3`
- `j==3`, `num[j]==2`
>一開始i=0的時候,我們check的目標num[i]是`1`,接著進入內迴圈,j從i+1開始遍歷陣列,也就是`2,3,2`中是否存在`1`,而不會check自己。
2. 在check完`1`之後發現`1`沒有重複,i就會+1,使得當前check的目標變為`2`。
3. `i==1`, `num[i]==2`
- `j==2`, `num[j]==3`
- `j==3`, `num[j]==2`
>`num[i]==2`時會分別check剩下的陣列`3,2`中是否存在`2`,不會check自己也不會check已check過的`1`。`j==3`時發現`2`有重複,就會回傳`2`。
***Optimization***
🍔: 謝謝你,可行性看起來是沒問題的,但是我們這個拍賣會的商品非常多,這樣的程式碼效能明顯還有改進的空間。請問你能想出更好的解決方式嗎?
🍤:好的,我想到了另一種解法。當遍歷nums列表時,或許我可以將元素添加到字典中,如果發現已經存在,就可以立即返回該元素,而不需要進一步遍歷。
🍔:聽起來是個不錯的想法,那請你開始撰寫code吧!
🍤:
```python
def findDuplicate(self, nums):
dic = {}
for n in nums:
if n in dic:
return n
else:
dic[n] = 1
return -1
```
好的,一開始先宣告一個空的字典,接著遍歷整個陣列,如果當前數字有出現在字典key中,就回傳這個數字;否則就將這個數字作為是字典中的key,並賦值1。跟剛才一樣,如果都沒重複的數字就會return -1。
接下來讓我測試這個程式是否可行。
```python
[3,1,3,4,2]
3 : 1
1 : 1
3 : exist -->return
[1,2,3,2]
1 : 1
2 : 1
3 : 1
2 : exist -->return
```
## [442. Find All Duplicates in an Array](https://leetcode.com/problems/find-all-duplicates-in-an-array/)
🍔:好的,謝謝。那假設今天不只有一幅畫是複製品,很多畫作都會有複製品,而你必須將所有有重複的編號整理給我,你會怎麼做呢?
🍤:我認為會需要一個陣列來儲存所有重複的數字。我的想法是,在剛才的程式碼中檢查此數字是否已存在的地方使用append將此數字加入到這個陣列中,最後輸出這個陣列就可以了。
🍔:好,聽起來沒什麼問題,請開始coding吧!
🍤:
```python
def findDuplicates(self, nums):
dic = {}
ans=[]
for n in nums:
if n in dic:
ans.append(n)
else:
dic[n] = 1
return ans
```
🍤:程式這樣就完成了,現在我想測試這個程式碼結果。
```python
[4,3,2,7,8,2,3,1]
4 : 1
3 : 1
2 : 1
7 : 1
8 : 1
2 -->ans.append, ans[2]
3 -->ans.append, ans[2,3]
1 : 1
return ans --> output:[2,3]
```
🍔:好的,感謝你今天參與這場面試,面試結果後續我們會再用email通知,請留意信箱,謝謝!
---
## 互評心得
在評其他同學作業的時候,我給予的正面評價有口齒清晰,表達得很完整,有些同學甚至不需要字幕也能聽懂,然後做了很多我沒想到的方面,比如說會在優化後驗證、複雜度分析等等。改進空間的部分則是有英文容易有語法錯誤、沉默時間太長並給出可以說甚麼的建議、驗證過於瑣碎導致花費很多時以及標註出一些沒有講清楚的地方。
在觀看其他同學的錄製的影片時,我發現有些同學講解程式碼講得很清楚,我聽一次就能聽懂,也從中學到了沒有看過的題型的解題方法和思路。有些同學編寫程式邊說明仍然可以說得很明瞭,不怎麼停頓,我覺得這是我還需要加強的地方,因為我很常卡住然後為了不那麼安靜就會說一些沒有意義的語助詞,如「呃」、「對」、「嗯」……等等。然後其他同學有的英文說的很好很自然,但我就會很常不知道一些英文單字的發音,以及如何組織一個句子,需要用翻譯軟體才知道自己怎麼說才正確。因為平常跟別的同學接觸也不太常用到英文,感謝這個作業讓我有看到別人的機會、知道自己不足的地方。
而在這份作業中,我也同時可以看到別人給我的評價,讓我可以看到自己平常不會注意到的方面。尤其是當我看到別人給我的肯定時非常開心,可能是因為平常真的很少聽到這方面的誇獎吧!所以就算下面馬上就看到自己的缺點,也會十分的有信心自己在之後的作業可以將這些優點全部改進。我認為此次作業互評帶給我非常正面的影響~
## 第四次作業-他評01
### 優點
* 面試全程咬字清晰,表達清楚,超讚
* [5:24](https://youtu.be/ElSse721QWM?t=324) 測試方式非常詳細,逐步解說讓人容易理解
### 可改進的地方
* [7:58](https://youtu.be/ElSse721QWM) interviewer 可以明確點出目前程式碼的缺點,但不提供作法,這樣可以與 interviewee 有很多互動,但又不會過度引導 (e.g. 雙層迴圈看起來有許多冗餘的步驟,同一個元素通常要被拜訪很多遍,你是否能夠讓程式更有效率?)
* [13:53](https://youtu.be/ElSse721QWM?t=833) 針對多幅畫作複製品的解法有 bug,如果今天的 input 為`[4,3,2,7,8,2,3,1,2]`,output 應該要是`[2,3]`,但程式碼的 output 是 `[2,3,2]`
* **建議 1**: interviewer 要補充 「一幅畫只會有一個複製品這個條件」
* **建議 2**: interviewer 要找出 bug 並提醒 interviewee 改進