<劍指offer> 題目整理

總結(jié)我做nowcoder oj上劍指offer的66道題時的一些感想(分三天回顧一下)。總得來說這66題大部分還不錯,字符串,鏈表,樹,堆,棧,雙端隊列,動態(tài)規(guī)劃,回溯,二分搜索都有涉及,但是題量還是小了些,比如回溯,初次接觸的人可能會一臉懵逼。國內(nèi)公司面試應(yīng)該不會超出這個程度。

代碼放在了github

1. 二維數(shù)組中的查找(4) [打分: 5/10]
在一個每一行每一列都遞增的二維數(shù)組里找一個數(shù)。trick是從左下角(或者右上角)開始找。
注意,這題在leetcode也有,同時有個類似題目:如果上一行最后一個小于下一行第一個數(shù)字怎么做?答案是binary search。

  1. 替換空格(5) [打分: 3/10]
    這題考的是c語言操作數(shù)組的技巧,c語言的話要先traverse一遍看有多少空格,然后定義新數(shù)組長度為oldnumber+replacenumber*2;Java可以用StringBuffer構(gòu)造或者直接用String.replaceAll

  2. 從尾到頭打印鏈表(6)[打分: 9/10]
    這題要能給出多種思路。
    Approach 1. 逆序鏈表。代碼略
    Approach 2. 用棧,空間O(n)。代碼略
    Approach 3. 遞歸,每次先打印后一個節(jié)點的值,缺點是可能stack overflow

  3. 重建二叉樹(7)[打分: 8/10]
    思路是定位root在inorder的數(shù)組中的位置,遞歸構(gòu)建。

  4. 用兩個棧實現(xiàn)隊列(9)[打分: 7/10]
    代碼短但是有一定的技巧。值得再做。

  5. 旋轉(zhuǎn)數(shù)組的最小數(shù)字(11)[打分: 8/10]
    Leetcode高分題search in rotated sorted array, 要點是找到一個ascending的區(qū)間進行搜索。值得做。

  6. 斐波那契數(shù)列(10) [打分: 7/10]
    經(jīng)典動態(tài)規(guī)劃(DP),早年fb面實習(xí)生簽到題。

  7. 跳臺階[打分: 7/10]
    經(jīng)典DP,思路同斐波那契。leetcode原題。

  8. 變態(tài)跳臺階[打分: 7/10]
    上一題的followup。

  9. 矩形覆蓋[打分: 7/10]
    同樣是斐波那契數(shù)列。轉(zhuǎn)移方程: dp [n] = dp[n-1] + dp[n - 2]

  10. 二進制中1的個數(shù)(15)[打分: 6/10]
    位運算。常規(guī)做法是對每bit都右移和1相與;更好的做法是把這個數(shù)持續(xù)地減去1并且與原來的數(shù)按位與運算(相當(dāng)于把原來的數(shù)最右邊的1變成0),然后重復(fù)這一操作。

  11. 數(shù)值的整數(shù)次方(16)[打分: 6/10]
    首先要考慮corner case;其次用遞歸求解更快。

  12. 調(diào)整數(shù)組順序使奇數(shù)位于偶數(shù)前面(21)[打分: 7.5/10]
    有點巧妙,類似插入排序(穩(wěn)定)。不要用額外空間。

  13. 鏈表中倒數(shù)第k個結(jié)點(22)[打分: 7/10]
    快慢指針,寫起來需要注意細(xì)節(jié)。

15.反轉(zhuǎn)鏈表(24)[打分: 7.5/10]
經(jīng)典老題。迭代好寫,遞歸難寫。

  1. 合并兩個排序的鏈表(25)[打分: 7.5/10]
    leetcode原題,去東京的飛機上寫過。迭代好寫,遞歸難寫。

  2. 樹的子結(jié)構(gòu)(26) [打分: 7.5/10]
    leetcode原題。子樹和子結(jié)構(gòu)不同。

  3. 二叉樹的鏡像(27) [打分: 7/10]
    難倒brew作者的easy題。

  4. 順時針打印矩陣(29) [打分: 3/10]
    沒啥意思的一道題。

  5. 包含min函數(shù)的棧(30) [打分: 7/10]
    跟第5題兩個棧實現(xiàn)一個隊列一樣有點tricky。

  6. 棧的壓入、彈出序列(31) [打分: 8/10]
    借助一個棧來模擬操作。有一定思維技巧,值得重復(fù)做。leetcode946題。

  7. 從上往下打印二叉樹(32) [打分: 8/10]
    BFS。送分題。不談了。

  8. 二叉搜索樹的后序遍歷序列(33) [打分: 8/10]
    BST的后序序列的合法序列是,對于一個序列S,最后一個元素是x (也就是根),如果去掉最后一個元素的序列為T,那么T滿足:
    T可以分成兩段,前一段(左子樹)小于x,后一段(右子樹)大于x,且這兩段(子樹)都是合法的后序序列。完美的遞歸定義 : )

  9. 二叉樹中和為某一值的路徑(34) [打分: 8/10]
    一道回溯題。跟BinaryTreePaths和CombinationSum的解法類似。需要注意的就是target的判斷和不要多remove一次。

  10. 復(fù)雜鏈表的復(fù)制(35)[打分: 6/10]
    leetcode原題。解法比較固定。
    第一步,在舊鏈表中創(chuàng)建新鏈表,此時不處理新鏈表的next和random(因為random指向的節(jié)點可能還沒初始化出來)
    第二步,初始化新鏈表的random
    第三步,分離兩個鏈表

  11. 二叉搜索樹與雙向鏈表(36) [打分: 6/10]
    把BST轉(zhuǎn)換成雙向鏈表。這題我不是很理解,也沒說要返回head。它的意思大概是說把tree.left當(dāng)做node.prev吧,那就中序遍歷,把cur.left指向prev,prev.right指向cur。這題好像是leetcode鎖住的一道題。

  12. 字符串的排列(38) [打分: 10/10]
    leetcode原題。經(jīng)典backtracking。

  13. 數(shù)組中出現(xiàn)次數(shù)超過一半的數(shù)字(39)[打分: 7/10]
    這題是典型的有點tricky的題,要記住。借助額外空間當(dāng)然簡單但是不是面試官想看到的答案。leetcode也有,摩爾投票法。

  14. 最小的K個數(shù)(40) [打分: 10/10]
    PriorityQueue與最小堆的應(yīng)用。

  15. 連續(xù)子數(shù)組的最大和(42) [打分: 9/10]
    經(jīng)典DP。Leetcode53題。Maximum SubArray。

  16. 整數(shù)中1出現(xiàn)的次數(shù)(從1到n整數(shù)中1出現(xiàn)的次數(shù))(43) [打分: 0/10]
    這題直接放棄了 Math的題,實在不想看。LeetCode 233題。

  17. 把數(shù)組排成最小的數(shù)(45) [打分: 7/10]
    這題就是LeetCode 179. Largest Number。簡單方法用一個Comparator來比較o1 + o2和o2 + o1的大小就行。另有一種奇淫巧技。

  18. 丑數(shù)(49) [打分: 7.5/10]
    這題是leetcode 264. Ugly Number II。brute force會TLE。要用DP。

  19. 第一個只出現(xiàn)一次的字符位置(50) [打分: 4/10]
    用Map就行。至少要遍歷一次。這題leetcode也有,一道easy題。

  20. 數(shù)組中的逆序?qū)?51) [打分: 7/10]
    考察merge sort。在merge sort基礎(chǔ)上加一行即可。值得做。

  21. 兩個鏈表的第一個公共結(jié)點(52) [打分: 8/10]
    方法1,Map,空間O(n),不太好。
    方法2,找出2個鏈表的長度,然后讓長的先走兩個鏈表的長度差,然后再一起走。值得重復(fù)做。

  22. 數(shù)字在排序數(shù)組中出現(xiàn)的次數(shù) [打分: 8/10]
    重復(fù)進行二分搜索。另有新穎解法: +-0.5。另外我覺得這題可以直接用c++的upper_bound和lower_bound來做。

  23. 二叉樹的深度(55) [打分: 7/10]
    DFS或者BFS都行。做爛了。

  24. 平衡二叉樹 [打分: 7.5/10]
    這題也比較tricky,要post order,否則多走很多路。

  25. 數(shù)組中只出現(xiàn)一次的數(shù)字 [打分: 6/10]
    這題考察XOR操作。

  26. 和為S的連續(xù)正數(shù)序列[打分: 9/10]
    滑動窗口法。值得做。

  27. 和為S的兩個數(shù)字(57)[打分: 8/10]
    這題跟two sum的區(qū)別就是這題是sorted array,所以可以用two pointers。

  28. 左旋轉(zhuǎn)字符串(10)[打分: 7/10]
    用substring就行。今天看到題解,是用類似旋轉(zhuǎn)整個字符串然后再部分翻轉(zhuǎn)的的思路;比如hello world單詞翻轉(zhuǎn),也可以看成是這題的特殊情況,從空格翻轉(zhuǎn)。這樣做更像是trick,唯一的好處就是不借助額外空間。

  29. 翻轉(zhuǎn)單詞順序列(10)[打分: 7.5/10]
    這題9月面試的時候問到,我直接用split來做,面試官一直提示我直接操作字符;現(xiàn)在想想他想看的是劍指offer上的解法,先翻轉(zhuǎn)每個單詞,再翻轉(zhuǎn)整個句子;或者先翻轉(zhuǎn)整個句子,再翻轉(zhuǎn)每個單詞。
    證明一件事情:無論你想的答案復(fù)雜度如何,面試官想看的永遠(yuǎn)是他看過的那個答案。

  30. 撲克牌順子(61)[打分: 9/10]
    我重新描述一下題目: 給一個數(shù)組里面有5個非負(fù)整數(shù),其中0可以看做任何數(shù),問這五個數(shù)能否組成連續(xù)序列。解法是one pass hashset(one pass兩個條件還挺巧妙的))。不用排序。

  31. 孩子們的游戲(圓圈中最后剩下的數(shù))(62)[打分: 8/10]
    約瑟夫環(huán)問題。
    編號0 ~ n - 1的小朋友圍成圓圈,從0開始依次數(shù)m - 1個數(shù),第m - 1個不再參與游戲;然后下一個人繼續(xù)從0開始數(shù),求最后剩下的人的序號。
    用Java的話可以用linkedlist模擬(不用真地首尾連起來,只要用mod計算循環(huán)index),可以模擬remove。linkedlist比arraylist插入刪除效率高,因為不用arraycopy。也可以用數(shù)組。

  32. 求1+2+3+...+n(64)[打分: 3/10]
    這題看了下書上,本意是用一些c++特性來求解。用Java的話可以用遞歸和&&。

  33. 不用加減乘除做加法(65)。[打分: 3/10]
    寫一個函數(shù),求兩個整數(shù)之和,要求在函數(shù)體內(nèi)不得使用+、-、*、/四則運算符號。方法是位運算。

  34. 把字符串轉(zhuǎn)換成整數(shù)(67)[打分: 5/10]
    這題是leetcode第8題。那題差評率高。解法沒啥意思,就是按位累乘。

  35. 數(shù)組中重復(fù)的數(shù)字[打分: 8/10]
    approach1, sort 復(fù)雜度高。
    approach2, map/set 需要額外空間。
    approach3, inplace substitution。無需額外空間,利用「長度為n的數(shù)組里的所有數(shù)字都在0到n-1的范圍內(nèi)」這個條件。思路是把nums[nums[i]]上的數(shù)字+length,這樣下次如果發(fā)現(xiàn)nums[nums[i]]已經(jīng)>=length了,說明已經(jīng)加過一次了。有一定思維難度。

  36. 構(gòu)建乘積數(shù)組(66)[打分: 7/10]
    這題要畫圖(上三角和下三角)才能做出來。有一定的思維技巧。

  37. 正則表達(dá)式匹配 [打分: 7/10]
    劍指offer上唯一一道hard題。對應(yīng)leetcode第10題。遞歸求解。

  38. 表示數(shù)值的字符串[20] [打分: 0/10]
    很沒價值的一題。如果這題因為漏了corner case而不能AC,無需責(zé)備自己。
    其實可以看下力扣用自動機的解法

  39. 字符流中第一個不重復(fù)的字符 [打分: 5/10]
    這題要用額外空間。我用了LinkedHashMap,然后對map.entrySet()做遍歷。也可以直接用HashMap

  40. 鏈表中環(huán)的入口結(jié)點(23)[打分: 7/10]
    最簡單的方法,找第一個重復(fù)的內(nèi)存,需要O(n)空間。
    劍指offer上的解法, 先用快慢指針判斷是否有環(huán),然后計算環(huán)的長度n,然后再用兩個指針,一個先走n步,一個從頭開始走,他們相遇的結(jié)點就是entry node。
    leetcode142、287題有快慢指針方法。

  41. 刪除鏈表中重復(fù)的結(jié)點(18)[打分: 7/10]
    runner和walker操作。
    另一題:O(1)時間刪除鏈表結(jié)點。注意corner case。

  42. 二叉樹的下一個結(jié)點(8)[打分: 7//10]
    給定一個二叉樹和其中的一個結(jié)點,請找出中序遍歷順序的下一個結(jié)點并且返回。注意,樹中的結(jié)點不僅包含左右子結(jié)點,同時包含指向父結(jié)點的指針。naive做法當(dāng)然可以從頭開始中序遍歷,但是效率不高。所以要找規(guī)律;如果有右子樹,則找右子樹的最左節(jié)點;如果沒有右子樹,則找第一個當(dāng)前節(jié)點是父節(jié)點左孩子的節(jié)點(因為當(dāng)前節(jié)點可能是父節(jié)點的右子樹)。

  43. 對稱的二叉樹(28)[打分: 8/10]
    代碼很巧妙,DFS或BFS都行。leetcode有。

  44. 按之字形順序打印二叉樹[打分:7/10]
    BFS送分題。

  1. 把二叉樹打印成多行[打分:7/10]
    BFS送分題。

  2. 序列化二叉樹(37)[打分: 8/10]
    leetcode經(jīng)典題,第二道hard。

  3. 二叉搜索樹的第k個結(jié)點(54)[打分: 7.5/10]
    inorder DFS,或者更巧妙地,計算右子樹節(jié)點個數(shù),類似二分。

  4. 數(shù)據(jù)流中的中位數(shù)(41)[打分: 9/10]
    這題非常巧妙,用兩個PriorityQueue.

  1. 滑動窗口的最大值[打分: 10/10]
    很巧妙,用ArrayDeque

  2. 矩陣中的路徑(12)[打分:9/10]
    leetcode的word search。經(jīng)典Backtracking。backtracking題要注意有的回溯時不需要重置標(biāo)志位,比如word island.

  3. 機器人的運動范圍(13)[打分:10/10]
    同樣是一道backtracking。注意不要重置標(biāo)志位。


以下是牛客oj沒有的題

  1. 剪繩子(14)
    題意:把一個整數(shù)分成至少兩份,返回最大可能的乘積值。
    這題很好,是劍指offer第14題,剪繩子。可以用動態(tài)規(guī)劃和貪心兩種方式來做。其中動態(tài)規(guī)劃有可以用記憶化來做。

  2. 打印1到最大的n位數(shù)(17)
    亞麻onsite題目。

  3. LCA問題

  4. 數(shù)字翻譯成字符串(46)
    top down recursion with memo或者bottom up dp,leetcode好像有
    dp[i] = dp[i + 1] + substring(i, i + 2) < 26 ? dp[i + 2] : 0

  5. n個骰子的點數(shù)(https://www.cnblogs.com/AndyJee/p/4686208.html)
    https://www.cnblogs.com/xuanxufeng/p/6896569.html
    在c-1個骰子的基礎(chǔ)上,再增加一個骰子出現(xiàn)點數(shù)和為k的結(jié)果只有6種情況:
    dp(c,k)=dp(c-1,k-1)+dp(c-1,k-2)+dp(c-1,k-3)+dp(c-1,k-4)+dp(c-1,k-5)+dp(c-1,k-6)(注意當(dāng)k<6時的處理越界問題)
    有1個骰子,dp(1,1)=dp(1,2)=dp(1,3)=dp(1,4)=dp(1,5)=dp(1,6)=1
    https://www.e-learn.cn/content/qita/2293425

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 前言 2. 實現(xiàn) Singleton 3. 數(shù)組中重復(fù)的數(shù)字 4. 二維數(shù)組中的查找 5. 替換空格 6. 從尾到...
    Observer_____閱讀 2,970評論 0 1
  • 樹 記錄《劍指offer》中所有關(guān)于樹的題目,以及LeetCode中的相似題目。 相關(guān)題目列表 題目 樹是一種最常...
    wenmingxing閱讀 1,439評論 2 13
  • 下面是我整理的,劍指Offer前五章所有的題目以及相關(guān)題和拓展題的題目和答案。代碼的話放在github上,您可以下...
    kikido閱讀 1,055評論 0 1
  • 今天是特種兵訓(xùn)練的第五天,每天早上的簽到我恐怕沒辦法完成需要請假了,因為那個時間點都在上課,很可惜,不得不請假。 ...
    FAB施施閱讀 182評論 0 0
  • 窗外的鞭炮聲徹夜鳴響,煙花接二連三地綻放,朋友圈被雞湯祝福刷屏,聊天窗口動輒彈出紅包。周遭的人窮盡各種方式提醒著新...
    聽見魚說閱讀 226評論 0 1