--- title: 2021 年資訊科技產業專案設計課程面試範例 tags: INFO2021 --- # 2021 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2021)」面試範例 > 貢獻者: 琪怪 ChiGuai > ==[video](https://youtu.be/_eIbSRmkFKo)== --- # info2021-homework1 ## Leetcode 66. Plus One (等級:Easy) ### 題目 ``` You are given a large integer represented as an integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from most significant to least significant in left-to- right order. The large integer does not contain any leading 0's. Increment the large integer by one and return the resulting array of digits. ``` ### 討論 - 從最小位數依序往高位數看 - 若該位數不是9,則該位數加1後return - 若該位數是9,則將該位數值設為0,再繼續探討下一個位數 - 若最高位數是9,則在vector的最前面插入1之後再return > 改進方案: 能否使用遞迴形式實作? ### 程式碼 ```cpp= class Solution { public: vector<int> plusOne(vector<int>& digits) { for (int i = digits.size() - 1; i >= 0; i--) { if(0 <= digits[i] && digits[i] < 9) { digits[i] = digits[i] + 1; return digits; } else { digits[i] = 0; if(i == 0) { digits.insert(digits.begin(), 1); return digits; } } } return {-1}; } }; ``` ### 程式碼(遞迴版本) ```cpp= class Solution { public: vector<int> plusOne(vector<int>& digits) { add_index(digits, digits.size() - 1); return digits; } void add_index(vector<int>& digits, int index) { if (digits[index] != 9) { digits[index]++; return; } else { digits [index] = 0; if (index == 0) { digits.insert(digits.begin(), 1); return; } add_index(digits, index - 1); } } }; ``` ## Leetcode 58. Length of Last Word(等級: Easy) ### 題目 ``` Given a string s consisting of some words separated by some number of spaces, return the length of the last word in the string. A word is a maximal substring consisting of non-space characters only. ``` ### 討論 - 從最開始依序往後找 - 主要探討前面一個index跟本身的index關係,藉此知道是開始新word、在word之間、結束一個word或是在空格堆中 - 若前一個index及現在的index非空,表示在word之間,則計數加1 - 若前一個index為空,現在的index非空,表示開始一個新字節,計數歸回1 - 若前一個index非空,現在的index為空,不做事(已於一開始設初始值為1) - 若前一個index為空,現在的index為空,不做事 - 至於計數從1開始,是避免一開始的第一個index無法跟前一個index去做比較 > 改進方案:為何不從後面開始找? - 探討前面一個跟本身是不是空格,決定Word是否需要重新計數 - 從最後面開始往前 - 若前一個index為空,現在的index非空,表示開始下一個新字節,可以break迴圈 ### 程式碼 ```cpp= class Solution { public: int lengthOfLastWord(string s) { int temp = 1; int i; for (i = 1; i < s.length(); i++) { if(s[i] != ' ' && s[i-1] == ' '){ temp = 1; } else if(s[i] != ' ' && s[i-1] != ' '){ temp ++; } else if(s[i] == ' ' && s[i-1] != ' ') { continue; } else if(s[i] == ' ' && s[i-1] == ' ') { continue; } } return temp; } }; ``` ### 程式碼(從後面開始往前找) ```cpp= class Solution { public: int lengthOfLastWord(string s) { int temp = 1; int i; for (i = s.length() - 1; i > 0; i--) { if(s[i] != ' ' && s[i-1] == ' '){ break; } else if(s[i] != ' ' && s[i-1] != ' ') { temp ++; } else if(s[i] == ' ' && s[i-1] == ' ') { continue; } else if (s[i] == ' ' && s[i-1] != ' ') { continue; } } return temp; } }; ``` ## Leetcode 151. Reverse Words in a String (等級: Medium) ### 題目 ``` Given an input string s, reverse the order of the words. A word is defined as a sequence of non-space characters. The words in s will be separated by at least one space. Return a string of the words in reverse order concatenated by a single space. Note that s may contain leading or trailing spaces or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces. ``` ### 討論 - 從最後面的index依序往前看 - 並且與前一個index比較判斷目前word的狀態 - 一個word結束,使用string的append功能將前一個word加到final_words之中 - 開始新的word,先將last的index設為目前的index,如果不是第一個word的話,先加進空白鍵 - 使用start跟last分別記下word開始與結束的index > 改進方案:試著用看看stringstream呢? ### 程式碼 ```cpp= class Solution { public: string reverseWords(string s) { string final_words; int last = s.length(); int start; int i; for (i = s.length() - 1; i >= 0; i--) { if (s[i] == ' ' && s[i+1] != ' ') { start = i + 1; final_words = final_words.append(s, start, last - start + 1); } else if (s[i] != ' ' && s[i+1] == ' ') { last = i; if (final_words.length() != 0){ final_words = final_words + ' '; } } if (i == 0 && s[i] != ' ') { start = i; final_words = final_words.append(s, start, last - start + 1); } } return final_words; } }; ``` ### 程式碼(使用stringstream) ```cpp= class Solution { public: string reverseWords(string s) { stringstream str(s); string temp; vector<string> vec; while(str>>temp) { vec.push_back(temp); } reverse(vec.begin(),vec.end()); string ans = ‘’; for(int i=0;i<vec.size()-1;i++) { ans = ans + vec.at(i); ans = ans + ‘ ‘; } ans = ans + vec.at(vec.size()-1); return ans; } }; ``` ## 初步檢討自己的表現 1. 語速偏慢,打字速度偏慢,對於鍵盤快捷鍵不熟 2. 講話講到一半會停頓下來打程式 3. 語句間很多冗詞贅字,例如:`那`、`然後` 4. 蠻常打錯字 5. 程式碼太長,無法完整顯示在螢幕上 # info2021-homework2 ## Leetcode 66. Plus One (等級:Easy) ### 題目 ``` You are given a large integer represented as an integer array digits, where each digits[i] is the ith digit of the integer. The digits are ordered from most significant to least significant in left-to- right order. The large integer does not contain any leading 0's. Increment the large integer by one and return the resulting array of digits. ``` ### 對話討論記錄 角色介紹 :boy: interviewer怪奇 :fish: interviewee 琪怪 :boy: 嗨,琪怪。我是interviewer怪奇。想請問你了解lvalue跟rvalue的定義嗎? :fish: 左值與右值通常出現在運算式中。左值常指的是運算式後還保留其狀態的一個物件,像是大部分的變數都是左值。而右值常指的是一個運算式過後其狀態就不會被保留了,就是一個暫時存在的數值。就像是int a = 4 + 3; a就是左值,4+3就是右值。 :boy: 請問`++x`與`x++`分別是左值還是右值呢? :fish: `++x`因為是先+1再賦值給x,所以是左值。而`x++`是先賦值給x,再+1,所以是右值。 :boy: 想請你實作一個function,它是一個vector,裡面將正整數的每個位數分開存放,從高位數開始依序存放到最低位數。要作的事情就是將這個數字加1並回傳。 :fish: 請問意思是如果有一個正整數123,存放在vector為[1,2,3]而我需要將123+1變124,再回傳[1,2,4]嗎? :boy: 沒錯!不知道你對這題有什麼想法? :fish: 可以從最低位數往高位數探討,若是該位數不是9,就將該位數加1並回傳。若是該位數是9,則將該位數設成0並往更高位數探討之。若是到最高位數都還是9,則除了將該位數設成0外,在vector的最前插入數字1。 :boy: 請你邊實作邊講解一下你的程式碼。 :fish: <開始邊打程式碼邊講解> :boy: 請問你知道vector.insert是怎麼實作的嗎? :fish: vector底層都是通過迭代器進行操作的,也就是指標。一開始會先檢查插入位置的有效性,由於增加容量會導致pos迭代器失效,所以我們可以先保存pos相對於起始位置的偏移量,增加容量後再將pos重新賦值。插入後,再更新vector的末位置值。 :boy: 時間差不多了,今天的面試就到這邊,謝謝。 ### 程式碼 ```cpp= class Solution { public: vector<int> plusOne(vector<int>& digits) { for(int i = digits.size()-1;i>=0;i--) { if(digits[i]!=9) { digits[i]++; return digits; } else { digits[i] = 0; if(i==0) { digits.insert(digits.begin(),1); return digits; } } } return {-1}; } }; ``` ## Leetcode 58. Length of Last Word(等級: Easy) ### 題目 ``` Given a string s consisting of some words separated by some number of spaces, return the length of the last word in the string. A word is a maximal substring consisting of non-space characters only. ``` ### 對話討論記錄 角色介紹 :boy: interviewer怪奇 :fish: interviewee 琪怪 :boy: 嗨,琪怪。歡迎來到下場面試。想請問你知道char array跟string之間的差別嗎? :fish: 在C語言中並沒有string,但是可以用char array來表示string, 但要特別注意char array使用`{}`給值時要在最後面加`\0`,使用""時則可以不用。 :boy: 如果用`{}`賦值但沒有加上`\0`會發生甚麼事呢? :fish: 因為char array會不知道字串結束,所以可能會出現亂碼。 :boy: 想請你實作一個函數,他會輸入一組字串,每個字之間可能有很多空格,請你回傳最後一個字的英文字母個數。如"the sky is blue",這時候因為blue有4個英文字母就要回傳4。 :fish: 請問如果blue後面有很多空格也是一樣回傳4嗎? :boy: 沒錯!後面的空格省略不作計算。 :fish: 我認為可以從最後面依序往前找,主要探討前面一個index跟本身的index關係,藉此知道是開始新word、在word之間、結束一個word或是在空格堆中 - 若前一個index及現在的index非空,表示在word之間,則計數加1 - 若前一個index為空,現在的index非空,表示word結束,可以break迴圈 - 若前一個index非空,現在的index為空,即將開始新字節,不做事 - 若前一個index為空,現在的index為空,不做事 :boy: 這樣子,如果只有"a"字串會回傳1嗎? :fish: 阿..因為初始的文字無法與前一個index比較,所以需要多加一個情況。如果初始index是文字的話,則回傳數字就必須再多加1。這樣應該就能符合上述所說情況。 :boy: 沒錯!請你邊實作邊講解一下你的程式碼。 :fish: <開始邊打程式碼邊講解> :boy: 為甚麼程式是從`s.length() - 1`開始呀? :fish: 因為string的最後一個index會存放`\0`代表字串的結束,但是這個index並不在word計算字數裡面,因此將他排除。 :boy: 時間差不多了,今天的面試就到這邊,謝謝。 ### 程式碼 ```cpp= class Solution { public: int lengthOfLastWord(string s) { int tem = 0; for(int i=s.length()-1;i>0;i--) { if(s[i] == ‘ ‘ && s[i-1] == ‘ ‘) { continue; } else if(s[i] != ‘ ‘ && s[i-1] == ‘ ‘) { tem++; } else if(s[i] != ‘ ‘ && s[i-1] != ‘ ‘) { tem++ } else if(s[i] == ‘ ‘ && s[i-1] != ‘ ‘) { break; } } if(s[0]!=’ ‘) { tem++; } return tem; } }; ``` ## 初步檢討自己的表現 1. 面試者出題時,題目與題目之間沒有連貫性 2. 還無法做到一邊講解,一邊打程式 3. 未留意程式間的{} #### 參考資料 - [vector相關操作](https://www.uj5u.com/qita/272616.html) ---- # 第三次作業-他評 ## Interviewer ## Interviewee - 語速和語氣很像在背課文,連用三倍速聽起來都有點卡卡的 QQ # 第三次作業-他評02 ## 優點 * 有重複問題和舉例討論 ## 缺點 ### [66. Plus One](https://leetcode.com/problems/plus-one/) [00:14](https://youtu.be/_eIbSRmkFKo?t=14) Interviewer的提問和後面的問題沒有關聯? [00:16](https://youtu.be/_eIbSRmkFKo?t=16) lvalue在C99規格書定義是`locator value`,rvalue也不是right value,所以不應將兩者的中文翻為左值或右值。 [00:49](https://youtu.be/_eIbSRmkFKo?t=49) Interviewee舉例時如果已經分享螢幕畫面給Interviewer,可以直接在說明時將範例打在文件上。 [01:02](https://youtu.be/_eIbSRmkFKo?t=62) post increment應該是回傳一個與舊值相等之暫時複製再對原變數+1,由於無法對此回傳做dereference,所以是rvalue,不是先賦值給x再+1。 [01:51](https://youtu.be/_eIbSRmkFKo?t=111) Interviewee的舉例應該直接考慮特殊情況(例如因為進位而多一位數),比較能展現對特殊情況的敏感度。 [02:20](https://youtu.be/_eIbSRmkFKo?t=140) Interviewee討論最低位數遇到9的情況時,由於前面舉例跟這個無關,應該另外打字列出。 [03:00](https://youtu.be/_eIbSRmkFKo?t=180) Interviewee不用特地將舉例刪掉。 [04:47](https://youtu.be/_eIbSRmkFKo?t=287) `i == 0`只會發生在最後,不需要每次進入迴圈都判斷,另外也忘了做進位。 [05:31](https://youtu.be/_eIbSRmkFKo?t=331) Interviewer說最上面的條件都不符合太含糊了,看不出來是因為甚麼特別的輸入,才需要回傳包含-1的vector。 [05:40](https://youtu.be/_eIbSRmkFKo?t=287) Interviewer突然改問vector.insert()底層怎麼實作怪怪的,應該是針對題目本身做延伸,例如:代表數字的輸入vector可以是負的,或者變成Linked List要怎麼處理。 ### [58. Length of Last Word](https://leetcode.com/problems/length-of-last-word/) [06:45](https://youtu.be/_eIbSRmkFKo?t=405) 跟前面一樣,Interviewer的提問和接著要問的問題無關。 [07:04](https://youtu.be/_eIbSRmkFKo?t=424) $\{\}$應該是大括號不是中括號,然後char array沒有一定要在最後補`\0`。(使用情境要有明確假設) [08:56](https://youtu.be/_eIbSRmkFKo?t=536) Interviewee講的條件比較多時,應該搭配游標或打字說明,不然Interviewer可能無法馬上吸收並理解Interviewee的想法。 [12:54](https://youtu.be/_eIbSRmkFKo?t=774) Interviewee的做法`if (s[0]!= ' ')`有問題。假如字串中包含超過一個word,`s[0]`又非空白時長度就會多算。若要解決Interviewer提出只有一個字元該怎麼辦的問題,應該將判斷移到for迴圈前面,並改寫成 ```c= if (s.size() == 1 && s[0] != ' ') return 1; ``` [13:49](https://youtu.be/_eIbSRmkFKo?t=829) 取`i = string.length() - 1`跟`\0`無關(C++ string也並非以\0判斷是否為結尾),而是因為索引值的範圍從`0`到`string.length() - 1`。 [14:07](https://youtu.be/_eIbSRmkFKo?t=847) Interviewee一開始取的整數型別變數名稱`tem`可以改叫`len`之類的,和結果比較有關連。另外這題可以不用一直判斷前後是否為空(直接從字串的尾端開始,先找到第一個非空白字元,再往前找到下個空白,兩者相減即可)。因此Interviewer最後應該適時給予提示並要求改進。 * Interviewer和Interviewee整體的對談太像是在念一對一考試的劇本,不夠自然。 * 大括號能省則省,節省寫程式的時間。 # 第三次作業-他評03 雖然說聲音比較低的是 interviewer,比較高的是 interviewee,但有時候聽不太出來差異 ## Interviewer - [1:26](https://youtu.be/_eIbSRmkFKo?t=86) 題目內容與 l value 和 r value 的相關性不強 - [7:19](https://youtu.be/_eIbSRmkFKo?t=439) 詢問一些比較細節的,確認 interviewee 的理解程度,不錯 - [13:39](https://youtu.be/_eIbSRmkFKo?t=819) 聽不出來 interviewer 是出於什麼原因詢問這個問題 ## Interviewee - [0:36](https://youtu.be/_eIbSRmkFKo?t=36) 講話可以帶有一些贅字,聽起來比較不會太吃力,可以用等號左邊和等號右邊來取代左值右值 - [0:50](https://youtu.be/_eIbSRmkFKo?t=50) 可以將舉例融合在前面陳述時直接打在 codepad 上 - [1:57](https://youtu.be/_eIbSRmkFKo?t=117) 一邊重複陳述確認題目,一邊示例,good - [4:08](https://youtu.be/_eIbSRmkFKo?t=248) 隨著思考邏輯寫程式,很容易理解 # 第三次作業 - 他評04 ## 總體評價 Interviewee/Interviewer 雙方完全就是在朗讀,以對方的視角來說,聽到『則將 XXX 設為 0,並往更高位數探討之。...』,我不會覺得他是在回答我的問題而是在背課文。 ## 第一題: + `lvalue` 和 `rvalue` 的差別這個問題本身就有問題。在 - Interviewer 使用的詞是 `lavlue` 和 `rvalue`,Interviewee 不應該擅自更改成『左值』與『右值』。 - `lvalue`,`rvalue` 等並不是一個「值」,而是 Expression 的分類。 - [這份文件的 3.10 Lvalues and rvalues](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf) 有更詳細的說明。 - 假設 `x` 是一個 object,`++x` 並也可能被 overload 成一個 `lvalue`,`xvalue` 或 `prvalue`。問這種問題應該要提供 `x` 的 type,若是一個自定義的 class 也應該提供 overload, constructor 和 deconstructur 的實作。 - 這個問題跟需要解的題目完全沒有關聯。 + Interviewer 說話太卡,會讓 Interviewee 懷疑 Interviewer 是不是根本不知道自己在考什麼。 + `vector<T>.insert()` 的實做我認為是個不太適當的問題。簡單來說可以看做是『在一個 Linked List 中插入一個額外的 node』。 - Interviewer 回答了迭代器操作,卻沒有回答 vector 的實作方式。這樣鐵定會被問『那,迭代器是什麼?』 『position 迭代器又是什麼』 + **Iterator 不是指標!!!!!!!!!!!!!:angry:** ## 第二題 + <span style="color:green">String 和 `char` array 的差異我就覺得是個很好的問題。如果沒有平常就玩 `<string.h>` 的習慣其實說不太出來,我覺得。</span> - 然而回答有點不盡人意。以中括號賦值聽起來很像 `char arr = [apple]`,我的意見是該稱為『對 array 賦值』。以雙引號更奇怪,應該說『string literal』。 - `\0` 應叫做 "null character". - 並非『不知道字串結束』,而是 `\0` 代表的是字串終結,有點反果為因。 + <span style="color:green">有詢問到 blue 後方的空格滿可以體現對題目例外的敏銳度。</span> + 『index 為空,則可以 break 字節』已經是兩岸三地一心同體了,用詞應該統一。 + 例外條件的對應沒有解釋到為什麼加一可以解決問題。 + 『為什麼要從 `str.lenth() - 1` 開始迴圈』也跟 null character 不太相關。`std::string str = "apple"; str.length()` 的確會得到 5,但減一的理由僅僅是因為 string 是 0-indexed,不會有 5 這一格。 - **再者,`std::string` 根本就不是 null-terminated.** - `std::string` 儲存的是字串長以及字串值,`\0` 在 C++ 中並不會讓字串結束。例如: ```c++ int main(){ string str; str[0] = '\0'; cout << str << "\n"; return 0; } ``` - 會輸出 ```shell esting ``` # 第三次作業-他評04 > 到中間就不太能夠分辨哪段是interviewer, 哪段是interviewee ## interviewer * [0:11](https://youtu.be/_eIbSRmkFKo?t=11) 沒有前後文描述就直接提問R value 跟 L value的定義,問法有點怪(憑空問問題的感覺)。 ## interviewee * [0:29](https://youtu.be/_eIbSRmkFKo?t=29) 對於interviewer的問題沒有確認就直接回覆,回覆內容也有許多東西沒有先說明清楚 * [1:06](https://youtu.be/_eIbSRmkFKo?t=66) 程式碼直接用唸的有點難反應過來,打在doc上可能會比較好理解 * [4:18](https://youtu.be/_eIbSRmkFKo?t=258) 開始寫程式碼後太多沒有聲音的時間,可以在寫Code的時候稍微注意排版就不用一直縮排