貢獻者: 德米安 Demi
video
題目不要一直寫,重點是作法
增加和主管討論的時間
留白時間很討厭
問一些關於題目相關的問題
定義function要精準不能亂扯
binary tree
cache friendly binary search
🧔:interviewer 👶:interviewee
參考網址:
🧔:想請先請Demi介紹Binary tree,他有什麼好處、缺點與應用。
👶:a binary tree is a tree data structure in which each node has at most two children, which are referred to as the left child and the right child. 他有 linked list 的好處,讓空間配置更自由,不用如 array 宣告連續的空間,並產生空間浪費的情況,然而又改進了 linked list 的問題,讓尋找節點更加容易,不須一個一個拜訪確認。缺點是如果沒有經過好的維護的話,會產生 imbalance tree 的問題,高度不一。那 Binary tree 有許多不同的變形,如最有名的紅黑樹,紅黑樹有很好的 tree depth 的維護方式與複雜度優化,那 linux kernel 有大量地使用紅黑樹。
🧔:那接著請Demi實作binary tree的操作。請同學看到Doc的第一題:這邊有一個Tree,那想請你針對Tree每一個子節點做sibling交換。
👶:好的那我們針對 Tree 的 sibling 做交換,比如說:
👶:那我剛開始想到的方法是用遞迴的方式,如果有子節點時先向下執行函數,把他看成是 subtree 來處理。結束條件是到達葉節點後回頭把每個 subtree 的 child siblings 做交換。依此完成 divide and conqueer 直到根節點完成交換後即結束全部的遞迴函數。
🧔:recursive的作法可能在特定情況下會出狀況,想請Demi想一下在各種情境的複雜度,還有可能遇到的問題?
👶:
🧔:那想請問有沒有改進的方法呢?
👶:我的想法是可以透過一個linked list的stack對我們要做invert的node做紀錄,將搜尋到的node紀錄在stack中,再逐一從stack中的node做invert,以使用iterative達到模擬recursive的做法。
🧔:不過這樣做還是使用stack吧?
👶:確實,不過recursion累積的是function type,所以相比起來用stack模擬的話是累積pointer type,應相比會小一些。
👶:如果我們把存起來的資料結構變成 queue 的方式,用廣度優先搜尋 (BFS) 做的話,是可以避免 stack 囤積無法釋放的狀況。
🧔:那剛剛有提到 recursion 可能會因為 imbalance tree 而導致 stackoverflow 的問題,那我想請 Demi 寫一個 function 去確認 Tree 的 max depth 是多少。
🧔:那延續這個 function ,最後驗證試試看這棵樹是不是 balanced tree。
參考網址:704. Easy Binary Search
參考網址:35. Easy Search Insert Position
參考網址:33. Median Search in Rotated Sorted Array
🧔:請看第二題,我首先提供一個 sorted vector<int> nums 和一個 int target ,那如果這個 target 在矩陣中則回傳給我索引值,如果沒有在裡面的話回傳給我-1。
👶:這一題最直覺的方法是使用Sequential Search的方式一個一個找值,然而這個方法的時間複雜度為。那在此我們可以用Binary Search的方式來讓時間複雜度降在內。
🧔:很好,那我這邊做一點變化,請同學另外複製這一段的程式碼,我現在希望你可以回傳給我此target在array的index,若target不在array中,則告訴我如果target插入array時,他的index是多少?
👶:那這一題是要讓我們進行search and insert的動作,我們一樣是透過 binary search 來找要插入的 index ,在最下面不再是 return -1 而是要插入的 index 值。所以我們找到 最後得知沒有空位後,在這裡開始判定應該插在 start 前面還是後面,這樣就完成了。
🧔:好的那最後面來一點大的變化,請同學先把程式改回 binary search 。那現在我會將 vector 內的值做前後挪移,比如我貼給你這個案例:我們可以看到這是一個被挪移調整過 k 次的矩陣,這些矩陣如果相反 k 次也可以恢復原本的 sorted array 的形式。那接著我 input 的 vector 也會是這樣的狀態,只是你不會知道我調整的次數為何?那我希望你幫我做 searching 的任務。如果有值回傳 index ,沒有的話回傳 -1。
👶:最直覺的做法就是,先用 binary search 找出總共挪移了幾次,找到值過後拿 nums[0] 作為 index 與 target 做比較,以此切開成前後兩半,接著繼續往這兩個區間做 binary search。
🧔:這樣做的話需要兩次 binary search 而且如果在挪移次數 k = 0的時候,似乎需要花很多時間搜尋。同學再想一下是不是有更好的方法,提示一下,可以從觀察 k = 2 and 6 在如果只做一次 binary search 的時候會遇到什麼情況。
struct TreeNode* invertTree(struct TreeNode *root)
才符合註解提供的原型ctrl + shift + 左 or 右
,把 invertTree 選取起來複製,看起來會更流暢shift + home
選取整行再複製,接著按 enter 到下一行也不必用 tab 縮排,直接貼上會更順暢q_push(q, val)
來當作把 val 推入 queue 裡面。q.empty
是錯誤的, queue.empty 是函數不是屬性,要寫成 q.empty()
才對q.push(node->left)
跟 q.push(node->right)
補上分號return NULL
而是 return nullptr
,這樣寫起來才有 C++ 的風格swap(root->left, root->right)
,所以程式是錯誤的,變成迭代版的做廣度優先走訪,而 interviewer 也沒有說是錯誤的return Max(left, right) + 1
,這樣版面會更美觀,可讀性也比較高int Max(int a,int b)
那一行,在按住 ctrl + shift + end
選取全部,接著再用 ctrl + shift + <
或 ctrl + shift + >
來調整字體大小這就是利用 binary search 尋找索引的方式
之類的話