leetcode题目总结
生活随笔
收集整理的這篇文章主要介紹了
leetcode题目总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 基礎算法
- 前綴和
- 哈希
- 雙指針
- 滑動窗口
- 二分
- 位運算
- mergesort
- quicksort
- 排序
- 桶排序
- KMP
- 數據結構
- 單鏈表
- 并查集
- 樹
- 排序樹
- 棧
- 隊列
- 圖
- Trie樹
- 線段樹
- 搜索
- bfs
- dfs
- flood fill
- 暴力
- 其他
- 貪心
- 動態規劃
- 背包問題
- 編輯距離類型
- 各種子序列問題
- 狀態轉移類型
- 數字三角形
- 線性簡單dp
- 數形dp
- 記憶化搜索
- 模擬題
- 博弈論
- 設計題目
- 數學推公式
基礎算法
前綴和
| 5144矩陣區域和-中 | 稍微變化了一下的二維前綴和。注意不要越界 |
| 1310. 子數組異或查詢-中 | 異或前綴和 |
| 274. H指數 | 直接模擬是O(nlogn)。其實可以先統計一下不同引用數量的論文各有多少篇(大于n的就當成n)。然后求個后綴和,cnt[i]的含義就是有cnt[i]篇論文引用數量大于i。只要i大于s,i就–。同時s加上對應的數值(就是后綴和) |
| 303. 區域和檢索 - 數組不可變 | 裸前綴和 |
| 304. 二維區域和檢索 - 矩陣不可變 | 裸二維前綴和 |
| 325. 和等于 k 的最長子數組長度 | 數字可能有負數,所以不能用雙指針(雙指針得要單調)。就用map記錄出現過的數字,sum記錄到目前為止的前綴和。如果出現過x,使得sum-x=k。也就是x=sum-k出現過,那就說明這一段之和為k,因為要最大值,所以記錄第一個出現的位置就好。 |
| 363. 矩形區域不超過 K 的最大數值和 | 前綴和+二分。這道題相當于要暴力所有不同大小的矩形。所以需要遍歷每個列,從當前列開始遍歷后面所有的列,同時用sum記錄所有行的之和。sum這個數組就記錄了從當前列開始,矩形的大小。然后要讓和<=k。就算對sum算一遍前綴和,sumj - sumi <= k => sumi >= sumj - k。用set存儲之前出現過的前綴和。用lower_bound找出>=sumj - k的前綴和。 |
哈希
| 不同的循環子字符串-良 | 題目寫的不清楚,我還以為要用KMP求循環結。實際上就是比較兩端是不是相同。直接字符串哈希。記住13111 |
| 30. 串聯所有單詞的子串-挺好 | 字符串哈希是真的好用啊。不過要主意好get哈希值的時候左右指針的位置。不過我這個算法也是O(n^2)的。 |
雙指針
| 1. 兩數之和 | 雙指針,排序之后從兩邊搜索。如果大了右指針往左移,否則左指針往右移。 |
| 2.兩數相加 | 一位一位算,記錄好進位就行 |
| 3. 無重復字符的最長子串 | 滑動窗口,雙指針。如果窗口內有重復數字,左指針就不斷向右移。 |
| 5.最長回文子串 | 每個點暴力搜索一下。記錄一下最大區間的左右端點。 |
| 11. 盛最多水的容器 | O(n)時間從左右兩邊搜索。每次都貪心的讓矮的一側往內走。記錄全局最大值就好。 |
| 15.三數之和 | two sum的擴展。遍歷第一個數,然后用two sum的方法算后兩個數。主要難點在于去重。第一個數去重:如果和上一個數相同就要continue。后兩個數去重:搜到一個結果的時候也要跳過和結果相同的幾個數字。 |
| 16.最接近的三樹之和 | 和上面這道題差不多,只不過每次都記錄一下和目標最接近的和 |
| 18.四數之和 | 就是遍歷前兩個數字,后面兩個數字用two sum的方法。去重可以用哈希表或者跳過重復數字。 |
| 26. 刪除排序數組中的重復項-水 | 一個指針往后找不重復的數,一個指針把數放在數組前面。 |
| 27. 移除元素-水 | 一個指針找不等于val的數,一個指針放置數字 |
| 28. 實現 strStr() | 雙指針或字符串 |
| 151. 翻轉字符串里的單詞 | 先整體反轉,再一段一段地反轉。多余空格的問題再額外多一個指針來專門放置字母。如果不處理后面的空格最后有可能會多一個空格,所以要預處理一下最后的空格。 |
| 167. 兩數之和 II - 輸入有序數組 | two sum同款,返回index就好 |
| 168. Excel表列名稱 | 26進制轉換 |
| 186. 翻轉字符串里的單詞 II | 這是151的簡化版本。 |
| 209. 長度最小的子數組 | 右指針不斷搜索。如果滿足條件就讓左指針不斷向右。 |
| 228. 匯總區間 | 貪心的來做就好。掃描每個數字,如果和下一個樹是連續的,就把這種區間都找出來,然后把結果加入返回數組中。 |
| 229. 求眾數 II | 用兩個變量統計最多的兩個數字。如果兩個變量大于三分之一。就把這個數加入到返回數組中。 |
| 240. 搜索二維矩陣 II | 雙指針,和之前遇到那道題也沒啥變化 |
| 283. 移動零 | 一個指針找非0元素,一個指針放置數字(交換就行)。 |
| 340. 至多包含 K 個不同字符的最長子串 | 一個指針加數字,另一個指針維護性質 |
| 392. 判斷子序列 | 簡單雙指針。 |
滑動窗口
| 76. 最小覆蓋子串 | 每次移動右指針,直到所有字母都包括在內。然后嘗試縮小左指針。直至不包括所有字母就再次移動右指針。 |
| 187. 重復的DNA序列 | 長度為10的滑動窗口 |
| 219. 存在重復元素 II | 用哈希表,如果哈希表個數大于k,就把最前面一個元素刪掉。 |
二分
| 4. 尋找兩個有序數組的中位數-好題 | 經典題目。把兩個數組分開考慮。兩個數組的左邊部分都應該小于等于右邊部分。否則,就是看看邊界情況。如果i0,說明a數組全都大于等于b數組。j0,就說明b全都大于等于a數組。 |
| 33. 搜索旋轉排序數組-挺好 | 經典題目。旋轉之后左邊的數都大于等于第一個數,右邊的數都小于(因為沒有重復的數)。所以先找到分界點。再根據target大小情況在左邊或者右邊的單調區間里面二分查找。 |
| 34. 在排序數組中查找元素的第一個和最后一個位置-不錯 | 二分就是要找到區間二分的性質。第一個數右邊的數都大于等于它,最后一個數左邊的數都小于等于它。記住取中位數的時候,如果是l=mid,記得要(l + r + 1) / 2。 |
| 35. 搜索插入位置 | 這道題翻車了。二分的時候如果等于就直接返回。否則等于mid+1或mid-1。這樣結果就正好是插入的位置。那個二分模板比較適合找范圍內的。這道題會搜到范圍外。 |
| 69. x 的平方根 | 比較扯淡的是要返回整數。所以等于就返回,大于r=mid-1, 小于l=mid+1 |
| 81. 搜索旋轉排序數組 II | 相比于33題有可能出現重復元素。就要把最后的和開頭相同的元素刪掉。注意不要刪空了,長度為1的情況要特判一下。 |
| 153. 尋找旋轉排序數組中的最小值 | 這個數組前半部分具有二分性質,都大于等于nums【0】。如果最初最后元素就比第一個元素大,那說明沒旋轉,直接返回第一個元素就好。 |
| 154. 尋找旋轉排序數組中的最小值 II | 主要是最后幾個數字可能和第一個數相同,把這幾個數字全都跳過就好。有一個很神奇的東西,在acwing n成為-1之后數組越界是沒問題的。在leetcode就需要特判一下。 |
| 162. 尋找峰值 | 首先peak是一定存在的。所以如果num【mid】》num【mid+1】。則peak一定在【l,mid】之間 |
| 275. H指數 II | 反轉之后,小于h指數的部分有二分性質:cit[m] >= m。不過有一些邊界情況。最后返回的時候要特判一下。 |
| 278. 第一個錯誤的版本 | 二分 |
| 374. 猜數字大小 | 標準二分 |
| 378. 有序矩陣中第K小的元素 | 第k個數肯定在最大值最小值范圍之內,就在這個范圍二分。對于一個mid,如果小于等于mid的數小于k個,l=mid+1, 否則r=mid。計算個數的時候,枚舉每一行,從右上角開始,向右找到第一個小于等于mid的數。加上j+1之后搜索下一行。復雜度是 O((m+n)log k) |
| 395. 至少有K個重復字符的最長子串 | 沒想到這是二分題目。從l到r。先計算這段每個字母出現次數。讓mid從l開始往r走。條件是cnt[s[mid]] >= k。如果mid走到了r說明這一段都ok。否則就計算(l, mid)(mid + 1, r)這兩段,取最大值。 |
位運算
| 50. Pow(x, n) | 注意指數的符號,以及溢出的問題。 |
| 136. 只出現一次的數字 | 進店簡單位運算 |
| 137. 只出現一次的數字 II | 經典位運算,有基于狀態機的解法,但是實在是沒記住。這種按位統計的算法比較直觀。 |
| 190. 顛倒二進制位 | 位運算 |
| 191. 位1的個數 | 位運算 |
| 201. 數字范圍按位與 | 這道題比較trick。其實我也不是很理解 |
| 231. 2的冪 | 2的冪只有一個1 |
| 260. 只出現一次的數字 III | 這兩個不同的數肯定有一位是不同的,把所有數異或之后,剩下的就是這兩個數的異或結果,使用lowbit得到最低一位。用這一位將所有數據分成兩堆,然后分別異或就可以得到最終結果。 |
| 289. 生命游戲 | 原地操作可以使用第二位保存新的狀態。 |
| 318. 最大單詞長度乘積 | 可以用位運算得到每個單詞中有哪些單詞。沒有重復就是 & 為0。 |
| 371. 兩整數之和 | a^b是不進位加法和。a&b << 1是加法后的進位。將兩部分不斷相加,直至進位全都加完即可。 |
mergesort
| 88. 合并兩個有序數組 | 就merge唄 |
| 315. 計算右側小于當前元素的個數 | 這道題真的不錯,計算每個位置的逆序對個數。記得不要重復申請釋放內存,很慢的,比如tmp我放在merge里面每次申請就會卡地超時。 |
| 327. 區間和的個數 | 這道題著實有點難,首先求前綴和就很難想到。然后對前綴和mergesort,求nums[r] - nums[l] 在 [lower, higher]區間內的數量,也不好想。 |
quicksort
| 215. 數組中的第K個最大元素 | 經典題目。我背的模板求的j是相對于l的第j個元素。l和j之間有(j-l+1)個元素。如果(j-l+1)> k。則在左邊繼續找第k個元素kth(l, j, k)。否則在左邊找第k-(j-i+1)個元素,kth(j+1, r, k-(j-l+1))。 |
| 324. 擺動排序 II | 有幾個注意點,1 如果元素是奇數個,則m=n/2+1。因為需要嚴格大于,小于。所以,要把小于mid放在前面,等于mid放在中間,大于mid放在最后。然后前m個和后n-m個逆序,再把兩部分合并(這是因為reverse之后中間相同的數字就會距離很遠,就不會相鄰了)。 |
排序
| 217. 存在重復元素 | 數字范圍沒說,只能排序或者用哈希表 |
桶排序
| 164. 最大間距 | 基于桶排序的算法,根據最大值最小值確定桶大小,再根據桶大小確定桶的個數,把所有元素映射到幾個桶之間。每個桶要記錄最大值和最小值。最終結果就在前一個桶的最大值和現在桶的最小值之間。 |
| 220. 存在重復元素 III | 哈希表保存最近的k個元素。然后把所有數據映射到寬度為t的桶之中。如果兩個數據大小之差小于等于t。那么他們一定在同一個桶或者相鄰的桶。 |
KMP
| 214. 最短回文串 | 直觀來想,在字符串之前加字母只能和字符串后面幾個字母匹配。前面的對稱部分不用管。前面對稱部分的長度可以用kmp算。把串翻轉再拼到后面,求一下next,next最后一個數據就是前面對稱部分的長度。 |
數據結構
單鏈表
| 19. 刪除鏈表的倒數第N個節點-還行 | 數據保證有效。因為有可能刪掉頭指針,所以建立虛擬頭節點。然后一個指針從虛擬頭節點先走n步,另一個指針同時走到底,這樣第二個指針就指向倒數n個節點的前一個,直接刪除就行。 |
| 21. 合并兩個有序鏈表-水 | merge就行 |
| 23. 合并K個排序鏈表-挺好 | 創建一個小頂堆,把k個鏈表的頭節點值和指針都放進去。以值為鍵。每次merge堆頂的元素就行。頭條面試問過這道題啊 |
| 24. 兩兩交換鏈表中的節點-不錯 | 第一個節點也要交換,所以要建立一個虛擬頭節點。pre指向兩兩每對的前一個,起初就指向虛擬頭節點。需要pre->next, pre->next->next都存在才能交換。p=pre->next, next = pre->next->next。交換就是:pre->next=next; p->next=next->next; next->next = p; pre=p;但是momanta問過這道題啊,然后我沒搞明白。這種題目就是要多畫一畫。 |
| 25. K 個一組翻轉鏈表-挺好 | 也要建立一個頭節點。然后往后走k步,把記錄一下頭尾節點和next,把tail->next=null,調用reverse(head)把這一段翻轉。這時候記錄的head就到了最后,head->next指向記錄的next |
| 61. 旋轉鏈表 | 首先計算鏈表長度。然后快慢指針。快指針先走k步,然后慢指針開始走,兩個指針走到底的時候,把前后兩段交換一下。 |
| 86. 分隔鏈表 | 用兩個鏈表分別保存,最后保存就好。 |
| 92. 反轉鏈表 II | 這是一道全考指針運算的題目。先建立虛擬頭節點。然后走m-1到第m個節點前一個。斷開后,把后面m-n個節點翻轉一下。然后和這一段前后連接在一起。 |
| 138. 復制帶隨機指針的鏈表 | 挺好的題目。先在每個節點后面都復制一個。然后把random指針全都連好。最后把新建的節點全都拿出來。 |
| 141. 環形鏈表 | 快慢指針看會不會相遇。 |
| 142. 環形鏈表 II | 快慢指針。慢指針走了t步,快指針走了2t步。假設相遇點為c,入口點為e。則 |
| 143. 重排鏈表 | 找到中點,逆轉后半個鏈表。然后交替merge就可以了。比較考察代碼能力 |
| 144. 二叉樹的前序遍歷 | 前序遍歷比較簡單,壓入棧中,彈出后遍歷,然后左右按順序入棧。 |
| 45. 二叉樹的后序遍歷 | 用兩個棧,so easy |
| 147. 對鏈表進行插入排序 | 思路很簡單,遍歷每個數據,然后在排好序的數據中找到合適的位置(大于等于數據的前一個位置)把數據插入。 |
| 148. 排序鏈表 | ologn,還要常數空間。就是用迭代的mergesort。思路就是從長度為1開始歸并,每次長度變大一倍。要記錄的指針比較多。每次切割出兩個長度為len的鏈表,然后合并。把結果和前面merge好的接在一起,再繼續取。知道len為n為止。 |
| 160. 相交鏈表 | 算長度,快指針多走幾步,然后兩個一起走,走到相遇就好。 |
| 203. 移除鏈表元素 | 建立一個虛擬頭節點處 |
| 206. 反轉鏈表 | 經典題目 |
| 234. 回文鏈表 | 找到中點,把后半部分逆轉(如果節點個數是奇數,要再往后走一個節點)。然后對比兩個鏈表是不是一模一樣。 |
| 237. 刪除鏈表中的節點 | 交換數據,刪除節點 |
| 328. 奇偶鏈表 | 遍歷模擬題 |
并查集
| leetcode5309. 連通網絡的操作次數-中 | 并查集算連通域個數,看看剩下的邊可不可以把幾個連通域連接起來即可 |
樹
| 祖父節點值為偶數的節點和-中 | dfs記錄的時候記錄父親和祖父的值即可。沒啥意思 |
| 94. 二叉樹的中序遍歷 | 中序遍歷最開始都是輸出最左邊的節點。所以每個節點都要先沿左邊走到底。然后棧pop,把結果放入隊列中。最后嘗試往右邊走。 |
| 95. 不同的二叉搜索樹 II | 如果要建立1—n的子樹。則根節點可以是1—n的任意一個。所以就遍歷每個分界點。然后遞歸生成左右兩邊所有子樹。然后遍歷左右所有子樹,和根節點連在一起。如果l==r。就返回一個節點。這個過程中會有重復,記錄一下中間結果。 |
| 96. 不同的二叉搜索樹 | 這道題其實是卡特蘭數。遍歷每個根節點。f(i)=f(j-1)*f(i-j) |
| 98. 驗證二叉搜索樹 | 二叉搜索樹是有序的。左邊子樹的數值都小于等于樹根。右邊子樹都大于等于樹根。所以記錄一下范圍,如果越過了范圍,就說明不是搜索樹。 |
| 99. 恢復二叉搜索樹 | 搜索樹的中序遍歷結果是有序的。所以就在中序遍歷的過程中,記錄出現逆序對的兩個節點。pre->val > cur->val。記錄兩個結點之后,最后交換一下就好。 |
| 100. 相同的樹 | 比較簡單。遞歸判斷左右兩邊就好。 |
| 101. 對稱二叉樹 | 相當于上一道題的延伸。兩棵樹是相同的,就說明這棵樹和自己是一棵樹,并且左右子樹是相同的樹。 |
| 102. 二叉樹的層次遍歷 | 記錄每一層的個數 |
| 103. 二叉樹的鋸齒形層次遍歷 | reverse一下就好,這樣最簡單。用雙端隊列太麻煩了,push的時候也要改變方向。 |
| 104. 二叉樹的最大深度 | easy |
| 105. 從前序與中序遍歷序列構造二叉樹 | 這個答案著實有點精妙。先序肯定是從前往后走的。所以只需要根據先序第一個元素找到中序的位置,然后遞歸構建左右子樹就好。 |
| 106. 從中序與后序遍歷序列構造二叉樹 | 和前序一樣。只不過后序指針從后往前走就好。 |
| 107. 二叉樹的層次遍歷 II | easy |
| 108. 將有序數組轉換為二叉搜索樹 | 取中點做根,遞歸處理左右節點。 |
| 109. 有序鏈表轉換二叉搜索樹 | 就是要額外寫一個找中點的函數。 |
| 110. 平衡二叉樹 | 求高度過程中如果發現高度差大于1,就不是平衡的 |
| 111. 二叉樹的最小深度 | 這道題主要關注一下邊界情況。如果只有一邊是空,則這空的這半邊不算的。 |
| 112. 路徑總和 | 到葉節點的時候判斷一下sum是不是空就好1 |
| 113. 路徑總和 II | dfs的時候記錄一下路徑的數值就好 |
| 114. 二叉樹展開為鏈表-好 | 這道題還是很精妙的。要把所有節點都連到right這邊。可以分多步考慮。首先把右邊摘下來。把左邊放到右邊。然后把右邊放在原來左邊的最右下處。然后往右邊走,直到所有左邊都移到了右邊。 |
| 116. 填充每個節點的下一個右側節點指針 | 這道題還是很巧妙的。根節點不用連接。使用根節點是可以把兩個子節點連接在一起的。然后遍歷這兩個子節點,使用同樣的方法把子節點所有的子節點全都連接在一起。(這道題是一棵完美二叉樹) |
| 117. 填充每個節點的下一個右側節點指針 II | 這道題不是完美二叉樹,但是依舊能用同樣的方法解出來 |
| 124. 二叉樹中的最大路徑和 | 最大路徑肯定是左右兩邊在加上根節點。所以遍歷所有節點,然后保留最大值就好。一側的最值要和0取max。 |
| 125. 驗證回文串 | 這讓我記住了兩個函數,isalnum判斷是不是字母和數字。tolower轉換成小寫字母 |
| 129. 求根到葉子節點數字之和 | dfs到根的時候把和加到總和就好。 |
| 199. 二叉樹的右視圖 | 又是一道層次遍歷 |
| 222. 完全二叉樹的節點個數 | 完全二叉樹的節點數量是確定的,所以可以二分最后一層節點位置。 |
| 101. 翻轉二叉樹 | easy |
| 235. 二叉搜索樹的最近公共祖先 | 因為這是二叉搜索樹,所以比較簡單,根據值就可以判斷當前是不是父節點了。如果不是搜索樹,就要搜索左右子樹,看左右節點有沒有p,q節點。再分情況。 |
| 236. 二叉樹的最近公共祖先 | 二叉搜索樹就需要不斷遍歷子樹,看子樹有沒有p,q。如果都有,說明當前就是父節點,否則,返回不空的左右就好。 |
| 257. 二叉樹的所有路徑 | dfs記錄路徑 |
| 297. 二叉樹的序列化與反序列化 | stringstream真的好用啊 |
| 331. 驗證二叉樹的前序序列化 | valid = next()=="#" |
排序樹
| 218. 天際線問題 | 這種掃描線沒做過。首先把左右區間全都放入multiset。為了區分左右斷點,左端點用負數,key還是坐標。然后按順序遍歷每個端點。同時用multiset記錄掃描到的高度。如果是左端點就把高度加入,如果是右端點,就把高度刪掉。同時記錄上一個點,如果最高高度不相同,就說明是轉折點,更新last,并把記錄結果。 |
| 230. 二叉搜索樹中第K小的元素 | 前序遍歷過程中遍歷到第k個的時候返回就好 |
棧
| 20. 有效的括號-水 | 棧頂比較一下左右括號匹不匹配就行 |
| 32. 最長有效括號-挺好 | 棧低記錄有效括號的前一個位置的坐標。初始為-1。如果遇到(就把坐標入棧。遇到)就出棧,如果一出棧棧空了就說明)不合法,再把當前左邊入棧。否則合法,并且此時棧頂為上一個(或者棧低坐標。這一段長度為i-stk.top()。后面有一道周賽求合法的括號是那些。每次合法括號匹配的時候都把括號左右坐標記錄下來。然后當成區間,合并區間,從連續區間里面找出最長的一段就行。到時候我面試就來這三道題目。 |
| 71. 簡化路徑 | 用棧模擬。不得不說,stringstream真的好用。getline(ss, string, delimiter)這個函數特特別好用。用來分割字符串特別爽。 |
| 84. 柱狀圖中最大的矩形-挺好 | 單調棧求出一個點左右第一個比他小的點的坐標。 |
| 85. 最大矩形-挺好 | 同樣單調棧。因為是矩形,情況太多不好算。所以就把每個點初始化成從這個點出發往右有幾個1。然后調用84題算出這一列的最大矩形。O(nm) |
| 150. 逆波蘭表達式求值 | 這是一個貪心的過程。注意棧里面第一個彈出來的是第二個操作數,后一個彈出來的是第一個操作數。如果是除法,要注意第二個操作數不為0。 |
| 155. 最小棧 | 再維護一個最小棧存儲相同位置最小數據 |
| 225. 用隊列實現棧 | 用棧實現隊列有多種形式。 |
| 316. 去除重復字母 | 字符c小于s1的尾字符,其尾字符在字符表中還有剩余,所以我們需要刪除尾字符,同時標記尾字符為沒有使用過 |
隊列
| 239. 滑動窗口最大值 | 裸單調隊列。如果不需要窗口的話,就是單調棧了 |
圖
| 207. 課程表 | 拓撲排序 |
| 210. 課程表 II | 拓撲排序 |
Trie樹
| 208. 實現 Trie (前綴樹) | 設置trienode,里面包含26個字母的指針,還有一個標記 |
| 211. 添加與搜索單詞 - 數據結構設計 | Trie樹 |
| 212. 單詞搜索 II | 這道題有多個單詞。所以就把所有單詞放到Trie樹中。然后在每個位置搜索一下。 |
線段樹
| 307. 區域和檢索 - 數組可修改 | 裸線段樹 |
搜索
bfs
| 獲取你好友已觀看的視頻-中 | 層次遍歷,保留level層的數據即可 |
| 1306. 跳躍游戲 III | 每次都能往兩個位置跳。最后看看0所在的位置有沒有跳到就行(跳過去的那些位置要加到隊列里) |
| 17.電話號碼的字母組合-還行 | 每個按鍵都對應三個字母。每次往三個新的字母擴展一下就行 |
| 126. 單詞接龍 II | 就是用bfs搜索,同時要記錄圖。雙端bfs是一種優化策略,奈何實在是有點難寫。 |
| 127. 單詞接龍 | bfs的時候記錄一下步數 |
| 133. 克隆圖 | 用哈希表記錄一下原來的節點和新建的節點之間的映射關系。bfs遍歷原來圖的時候,根據映射關系把新建節點加入哈希表里記錄的對應節點的neighbor列表中就好。 |
| 310. 最小高度樹 | 從最邊緣的節點開始bfs,知道中間只剩1或2個元素的時候停止,這就是離邊緣最近的根 |
dfs
| 22. 括號生成 | dfs+剪枝。優先開括號個數要小于n,閉括號個數要小于開括號個數。如果滿足這兩個條件就能繼續搜索。 |
| 36. 有效的數獨-還行 | 這道題目只是判斷一下比較簡單。數獨、八皇后就記錄好幾個位置的映射關系。數獨每塊就是模三除三。n皇后反對角線對角線就是x+y和n+x-y。然后暴力搜索就行。 |
| 37. 解數獨 | 記錄好映射就好。 |
| 39. 組合總和 | 直接搜索。每個值都可以重復用。還要避免重復。避免重復就把數組排個序,然后遞歸dfs的時候記得從當前位置 i 出發。 |
| 40. 組合總和 II | 每個數字只能用一次。就從i+1開始dfs下一輪。因為有重復數字。所以每次枚舉數字的時候都把重復數字跳過(要i>index)。 |
| 46. 全排列 | 經典dfs |
| 47. 全排列 II | 要去重,1排序使得相同數字在一起,2 如果前面一個數字和自己相同,并且前面的沒有被占用。 說明如果自己選用了,和前面一模一樣。所以要跳過重復 |
| 51. N皇后 | 主要是對角線和反對角線的對應關系。x+y和n+x-y。然后一行一行搜索就行,每次遍歷每一列,嘗試放入看是不是解。 |
| 52. N皇后 II | 和上面沒區別 |
| 60. 第k個排列 | dfs搜到第k的時候停止 |
| 77. 組合 | dfs,組合式枚舉要去重,就記錄一下現在dfs到了哪個位置。從這個位置開始繼續dfs |
| 216. 組合總和 III | dfs,不能重復,順序沒關系,就記住一個index,下次搜索從index開始。 |
| 282. 給表達式添加運算符 | 每次記錄一個位置,pos,從pos開始遍歷所有長度。把一段數字轉化成數字。如果小于INT_MIN,就嘗試添加三種操作符,這里如果pos是0,說明是第一個字符,就不需要添加操作符。因為x的優先級比較高,如果+后面有x,x就應該和上一個數據先結合,把相乘的結果加到當前數據上,即cur-prev+prev*num。 |
| 301. 刪除無效的括號 | 首先計算一下不合法的左右括號的個數,然后遍歷整個序列,如果遇到括號,就嘗試刪掉,然后繼續dfs。如果不合法的左右括號都刪掉了,就看看是不是有效的括號序列。 |
| 332. 重新安排行程 | 這道題比較騷的就是反向插入。用一個vector記錄能到達的點,然后排序之后從小開始,每次要把小的pop掉。如果沒有dest了,說明走到頭了,就把改點放入結果中。返回的時候要把結果reverse一下 |
| 386. 字典序排數 | dfs每種情況。傳入k,然后遍歷從i=0—9, 遍歷k*10+i。只要k小于等于n,就把k加入返回數組中。 |
| 399. 除法求值 | 建立一個圖g[a][b]. 表示a/b。對于一個請求c/d,就在圖里找一遍c到d的路徑。算路徑距離的時候要用乘法。 |
flood fill
| 130. 被圍繞的區域 | 先遍歷一下所有邊緣。在遍歷所有節點就好 |
暴力
| 1307. 口算難題-中 | 暴力的時候要順便計算左右量變的數量值,否則會超時 |
| 78. 子集 | 使用二進制直接暴力所有可能即可 |
| 79. 單詞搜索 | 遍歷每個字母,如果和首字母相同,就dfs一下。 |
| 90. 子集 II | 要去重。如果前一個字母和當前字母一樣,并且前一個字母沒選。那選擇當前字母和選擇前一個字母是一模一樣的。選了當前字母的話就重復了。所以要跳過這種情況。 |
| 93. 復原IP地址 | 最多也就12位,直接暴力所有結果。寫dfs的話, 還挺麻煩的。 |
| 149. 直線上最多的點數 | 這道題就是暴力搜索所有兩個點,然后計算從這個點出發,所有斜率相同和同一位置的點的數量,記錄最大值。所以重要的如何表示斜率。可以用dx,dy來表示。如果dx,dy有一個為0,就直接返回。否則求一下最小公約數,把兩個數化簡一下。 |
| 306. 累加數 | 這道題更多的是字符串處理的細節以及大整數加法。前兩個數只能暴力枚舉,前兩個數確定之后,后面的數就只用根據規則判斷。 |
其他
| 74. 搜索二維矩陣 | 從左上或右下開始搜索就行。每次會少一行或一列。復雜度是O(n+m) |
貪心
| 45. 跳躍游戲 II | |
| 53. 最大子序和 | 這道題,我是有點理解不了。如果和大于0就把當前數加到sum里。否則sum就等于當前數。 |
| 55. 跳躍游戲 | 剛開始只能到1號位置。mxpos=1,往后遍歷每個數字,如果mxpos >= i+1。就說明能到 i 這個位置,此時就能嘗試更新mxpos=max(mxpos, i + 1 + nums[i]); |
| 56. 合并區間 | 記錄區間端點st,ed。 |
| 57. 插入區間 | 插入后用上面的代碼 |
| 134. 加油站 | 只要油的總和大于等于消耗,就肯定能走一圈。至于從那個店出發,如果油不夠了,這一段肯定走不通。肯定要從下一站開始走。 |
| 135. 分發糖果 | 這道題說是hard不太準確。首先每個人都至少分1個。然后先從前往后遍歷,如果當前元素比前一個大,那當前元素肯定是前一個元素分的糖果數量加一。然后再從后往前遍歷,如果當前元素比后一個元素大,f【cur】=max(f【cur】,f【cur+1】+1) |
| 179. 最大數 | 這道題是貪心的。a,b兩個數,如果(a+b)大于(b+a),a就應該排在前面。這個比較關系是滿足傳遞率和反對稱性的。所以只要根據這個規則把數組排序就好。 |
| 330. 按要求補齊數組 | 要拼成一個數,一定要有小于等于這個數。初始化能拼成的數為[1,1),就是一個都沒有,miss=1,如果一個數nums[i]<=miss, 說明miss這個數能拼成連續區間。即[1, nums[i] + miss),然后看下一個數,nums[i]>miss,說明有缺失,要補充數字,補充的數字要盡量大并且要組成連續區間,所以就選擇miss。這樣就能拼成[1, miss+miss)里的所有數。 |
| 373. 查找和最小的K對數字 | 最小的k對數,其和也是最小的。就遍歷所有可能,把所有的和都存下來,排個序,取前k個就好。 |
| 402. 移掉K位數字 | 掃描每個字母。如果字母比棧頂小,就pop棧頂。有幾個coner case。如果棧是空,并且字母是0,不要入棧。如果掃描所有字母后k還沒用完,就pop k 個。 |
動態規劃
背包問題
| 322. 零錢兌換 | 完全背包,f(i, j) = min(f(i- 1, j), f(i, j - v)+w)。這里w為1 |
| 377. 組合總和 Ⅳ | 完全背包求方案數。因為順序不同就算做不同組合。所以要先遍歷體積,再遍歷物品(這里我也不是很懂)。 |
編輯距離類型
| 讓字符串成為回文串的最少插入次數-良 | 再區間左右兩側都可以插入,如果相同就無需操作。不相同就看看插左邊和插右邊那邊比較小。 |
| 10.正則表達式匹配 | 經典dp問題,這道題*可以匹配前面的字母任意多次。所以如果跳過的話,也跳過字母和通配符 |
| 44. 通配符匹配 | 經典問題,這道題*可以匹配任意字符串。所以可以匹配一個,或者跳過通配符。f(i, j)表示a的i后面和b的j后面是否匹配。 |
| 70. 爬樓梯 | f(i)表示走到 i 號樓梯可能的走法數目。f(i)=f(i-1) + f(i-2) |
| 72. 編輯距離 | 經典題目。f(i, j)所有將a[1-i]變成b[1-j]的操作方式中操作次數最少的操作。對于三種操作,刪除:說明要把a[1,i-1]變成b[1,j],f(i-1, j)+1。增加一個字母,加的字母和b[j]相同,則a[1,i]和b[1,j-1]相同,f(i, j-1)+1。修改,a[i] 改為b[j], 說明a[1,i-1]=b[1,j-1],f(i-1, j-1)+1。當然如果a[i]=b[j],則無需操作,f(i-1, j-1)。四種情況取min即可 |
| 115. 不同的子序列-不錯 | f(i, j)表示t的前j個字母由s的前i個字母的子序列組成的個數。要組成t的前i個字母。可以只看最后一個字母。f(i, j - 1)表示s的前j-1個字母的子序列能組成t的前i個字母的個數。如果t[i-1]==s[j-1],就可以加上f(i - 1, j -1),就是說s的前j-1個字母只要可以組成t的前i-1個字母就ok,應為最后兩個字母一樣。 |
| 132. 分割回文串 II | 1,如何快速判斷一段子串是不是回文的,f(i,j)表示s【i,j】這一段是不是回文的。長度為一的全是回文的,長度是2的也可以預處理一下。然后遍歷i,j。如果i,j兩個字母一樣,并且f(i-1,j-1)為真,則f(i,j)也為真。g(i)表示前 i 個字母切割成回文串的最小花費。如果f(0,i)為真,則g(i)為0。否則將g(i)初始化為 i ,這肯定是正確的。然后 j 遍歷每一個位置,如果【j, i】這段是回文的,就更新g(i)=max(g(i), g(j - 1)+1)。 |
| 139. 單詞拆分 | f(i)表示前i個字母可不可以被表示出來。更新f(i)的時候,就遍歷所有j=【0, i】。如果f(j)為真,并且【j,i】存在于單詞列表中,f(i)就為真。 |
| 140. 單詞拆分 II | 記錄一下每個狀態是由哪個狀態轉移過來的,最后反推一遍就好。 |
各種子序列問題
| 300. 最長上升子序列 | n^2的定義是:f(i)為nums[i]結尾的最長長度。nlong的定義是,f(i)為長度為i的序列結尾最小元素是多少。 |
| 368. 最大整除子集 | 這道題的主要問題是如何判斷一個子集是可以整除的。首先將數組排序,如果有a[i] < a[j],并且a[i]能夠整除a[j]。并且整除關系是可以傳遞的a[i] 整除 a[j], a[j] 整除 a[k]。則a[i]也可以整除a[k]。所以和300題一樣。如果a[i]整除a[j], f[j] = f[i] + 1。不過這里要記錄一下方案。用prev記錄f[j]是從前面哪個數跳過來的。 |
狀態轉移類型
| leetcode5310. 二指輸入的的最小距離-好 | f(i, a, b)表示按了前i個字母,并且第一根手指在a,第二根手指在b的所有按法中距離最短的那種按法的距離之和。O(n^3) |
| 91. 解碼方法 | f(i)表示到 i 這個字母最多有多少種轉移方法。f(i)可以由f(i-1),f(i-2)轉移過來。前者的條件是上一個字母不為0,后一個的條件是前兩個字母符合條件。 |
| 97. 交錯字符串 | f(i,j)就表示s3的 i+j 個字母是由s1的前 i 個字母和s2的前 j 個字母組成的。所以由兩種情況s3[i+j] 和 s1[i] 相同,這種情況只需要 f(i - 1, j) 是true就可以。或者s3[i-j] == s2[j]。這種情況 f(i, j - 1) 為true。 |
| 121. 買賣股票的最佳時機 | 這道題是比較經典的狀態轉移題目。有兩種狀態:有股票=1,無股票=0。f(i, k)表示到了第i天,手中有(k=1)無(k=0)時最多的錢數。f(i, 0) = max(f(i-1, 0), f(i-1, 1) + w[i])。f(i,1)=max(f(i-1, 1), -w[i])。最終結果是f(n, 0)。初始化的時候f(0, 0)=0, f(0, 1)=-w[i]。 |
| 122. 買賣股票的最佳時機 II | 和上面一道題的差別是,這道題可以多次交易。所以f(i, 1)=max(f(i-1, 1), f(i-1, 0)-w[i])。其他都不變。也可以把空間優化成常數的。 |
| 123. 買賣股票的最佳時機 III | 這道題說可以交易兩次。f(i, k, 0/1)表示交易到第i天,交易了k次,手里有(1)無(0)股票時最大收益是多少。每次買入算作一次交易。f(i,k,0)=max(f(i - 1, k, 0), f(i-1, k - 1, 1) + w[i]), f(i, k, 1)=max(f(i - 1, k, 1), f(i - 1, k - 1, 0)-w[i]) |
| 152. 乘積最大子序列 | maxDP[i + 1] =max(maxDP[i] * A[i + 1], A[i + 1],minDP[i] * A[i + 1])minDP[i + 1] = min(minDP[i] * A[i + 1], A[i + 1], maxDP[i] * A[i + 1]),dp[i + 1] = max(dp[i], maxDP[i + 1])。其實只需要保存三個變量。mx,mn,ret。如果當前數值為負數,則大數字乘負數會變成小負數。 |
| 188. 買賣股票的最佳時機 IV | 這里面k就很有意思。如果k大于n/2。那相當于交易次數無限制。否則f(i,j,0/1)表示交易到第i天,交易了j次,有或無股票的時候的最大錢數。i,j是要遍歷的。f(i,j,0) = max( f(i - 1, j, 0), f(i - 1, j, 1) + w[i]), f(i, j, 1)=max( f(i - 1, j, 1), f(i - 1, j - 1, 0) - w[i] ), 規定買入算一次交易結果是 f(n, k, 0)。 |
| 309. 最佳買賣股票時機含冷凍期 | f(i, 0)=max(f(i-1, 0), f(i-1, 1) + w[i]), f(i, 1)=max(f(i - 1, 1), i >= 2 ? f(i - 2, 0) : 0 - w[i]) |
數字三角形
| 62. 不同路徑 | dp(i,j)表示走到這個點的路徑數量。dp(i,j) = dp(i - 1, j) + dp(i, j - 1)。dp(1,1)=1。 |
| 63. 不同路徑 II | 有障礙的位置跳過就好 |
| 64. 最小路徑和 | f(i,j)表示走到這個點的最短距離。f(i,j)=min(f(i - 1, j), f(i, j - 1)) + w[i][j] |
| 118. 楊輝三角 | f(i, j) = f(i - 1, j) + f(i-1,j-1)。如果j0或ji,說明是第一個或最后一個,只加f(i-1,j)。 |
| 119. 楊輝三角 II | 這道題也是挺巧妙的。第k行有k+1個元素。首先把第一個元素設置為1。然后重復k次,每次從后往前f(i)+=f(i-1)。從后往前是為了避免前面已經更新過的結果。 |
| 120. 三角形最小路徑和 | 可以在原數組上直接求。注意一下邊界情況和初始值就好。 |
| 174. 地下城游戲 | 如果是負數-a,就要生命值至少是a才能走進這個格子。f(i,j)表示從(i,j)走到目的地需要的最小生命值。f(i,j)=min(f(i+1,j),f(i,j+1))-w(i,j)和0 取max。當然邊界情況取不到的時候就不要取了。 |
| 221. 最大正方形 | 如果一個點為1,則以這個點結束的正方形的變長為max(f(i - 1, j), f(i, j - 1), f(i - 1, j - 1)) + 1。 |
線性簡單dp
| 198. 打家劫舍 | f(i)表示到i這一點最大收益。f(i)=max(f(i - 1), f(i - 2) + w[i]) |
| 213. 打家劫舍 II | 圍成了一個圈之后,首尾兩個元素不能一起選到。所以就是nums[0, len - 1], nums[1, len]用198算兩個結果,取最大值就好 |
| 279. 完全平方數 | f(i)表示用平方數組成i這個數最小的個數。f(i)=min(f(i), f(i - j * j) + 1), i - j * j > 0; |
| 338. 比特位計數 | f(i)表示i這個數有多少個1。f(i) = f(i >> 1) + i & 1. |
| 343. 整數拆分 | f(i)表示i這個數最大是多少。i可以分成兩部分,j 和 i - j。 f(i) = max ( f(i), max ( f(j), j) * (i - j) ) |
| 376. 擺動序列 | up表示到目前為止,最后一步向上走的序列長度,down表示到目前為止,最后一步向下走的序列長度。up = max(up, down + 1), down = max(down, up + 1)。要求分別是a[i] > a[i - 1] 和 a[i] < a[i - 1] |
數形dp
| 337. 打家劫舍 III | f(i, j)表示i這個點,搶(1)或不搶(0)的最大值。f(i, 0) = sum(max(f(c, 0), f(c, 1))), f(i, 1) = i.v + sum( f(c, 0) ) |
記憶化搜索
| 241. 為運算表達式設計優先級 | 表達式所有加括號的可能。如果搜到了運算符,就遞歸運算左右兩邊。然后遍歷兩邊結果,根據運算符把結果加到返回數組中。 |
| 312. 戳氣球 | 區間dp,f(i,j)表示戳 i,j 這幾個氣球得到的最大分數。為了避免邊界問題,在首尾加上一個1。f(i, j) = max(f(i,j), f(i, k - 1) + nums[i - 1] * nums[k] * nums[j + 1] + f(k + 1, j)) |
| 329. 矩陣中的最長遞增路徑 | 這道題dp順序不好確定,但每個點序列長度是一樣的,所以就遍歷每個節點,最后記錄一下節點的序列長度就好。 |
| 375. 猜數字大小 II | 這道題說的是至少多少,所以f(i,j)表示猜出i-j范圍內的數的最小話費。f(i,j) = f(i, k - 1) + k + f(k + 1, j)。枚舉所有k,然后記錄最小值就好。 |
| 403. 青蛙過河 | 這道題有點遞推的感覺。開始只能走1步。如果上一步走了k步,下一步就可以走k-1, k, k + 1步。所以記錄沒給點能由哪些步數走到。對于每個步數k,遍歷k-1, k, k + 1。并把步數加到相應的位置。最后查看最后一個位置能不能走到就好。 |
模擬題
| 解壓縮編碼列表-水 | 水題 |
| 1309. 解碼字母到整數映射-水 | 注意從后往前模擬,這樣不會有歧義 |
| 5307. 將整數轉換為兩個無零整數的和-水 | 直接暴力 |
| 5308. 或運算的最小翻轉次數-水 | 一位一位算 |
| 6. Z 字形變換 | 建立n個數組,然后一行一行模擬。先往下走,如果走到頭了,就轉換方向就好。這道題還比較有意思 |
| 7.整數反轉 | 比較水 |
| 8.字符串轉整數 | 這道題主要就是記錄符號。然后累加數字的時候要注意會不會超過范圍。如果是正數,num>INT_MAX/10 |
| 9.回文數 | 轉換成字符串或者把每一位都摳出來都行 |
| 12.整數轉羅馬數字 | 也是貪心的做。羅馬數字從大到小排列。注意900,400,90,40,9,4這種數字是對應兩個羅馬字母的。 |
| 13.羅馬數字轉整數 | 和上面一道題相反,這道題也是貪心地做,不過每次從開頭先貪心地找有沒有連個羅馬字母,沒有的話再去找一個羅馬數字 |
| 14.最長公共前綴 | 多個字符串地最長公共前綴。也沒啥好辦法,就是一位一位地嘗試。 |
| 29. 兩數相除 | 用減法模擬除法的過程。為了優化速度。每次都倍增,加的i也倍增。如果比被除數大了,就讓除數變為最初的除數 |
| 31. 下一個排列-挺好 | 這道題得好好觀察。要求下一個比較大的排列。3 2 1這種全降序的是沒有比他大的排列的。所以要從后往前找到第一個正序對 1 【2 5】4 3。【2,5】就是一個正序對。正序對的第一個和最后一個字母交換得到1 3 5 4 2。2變成了3肯定是變大的。后面的全是降序的,然后把正序對第二個靠后的部分全都翻轉一下就得到了結果: 1 3 2 4 5。如果沒有正序對,就把整個串翻轉一下。 |
| 38. 外觀數列,一般 | 循環n次,根據題目模擬。 |
| 41. 缺失的第一個正數 | 這道題首先一共有n個數,如果缺失的正數在1~n之中。那么根據抽屜原理,這個數組里面一定有數字在1—n這個范圍外。則數值1—n之間的數換到坐標1—n之間之后。一定會有一個位置,數值和坐標不一樣。(因為數值是1—n的,坐標是0—n-1的,所以數值都要減1)。 |
| 42. 接雨水 | 這道題記錄每個點左右最高的柱子就行。記錄一邊最高的柱子,只需要記錄一下最大值就行。 |
| 43. 字符串相乘 | 主要是模擬。a是n位,b是m位。那么成績就是n+m位。a的第i位和b的第j位相乘之后,其實結果是ret的第i+j+1位。進位在i+j位(應為高位在前)。所以每次tmp=a[i] * b[j] + ret[i + j + 1]。ret[i+j+1] = tmp % 10, ret[i+j] += tmp / 10; |
| 48. 旋轉圖像 | 這道題是正方形,還比較簡單,每次交換四個點的位置就行。 |
| 49. 字母異位詞分組 | 這道題比較簡單。配個單詞排序或者記錄一下字母數量就行。排序是最簡單的。 |
| 54. 螺旋矩陣 | 經典題目,記錄好邊界和訪問過的位置。每次一個方向走到頭就換個方向。 |
| 58. 最后一個單詞的長度 | 找到最后一個不為空格的字符, 在從這里開始找第一個空格 |
| 59. 螺旋矩陣 II | 和54題差不多 |
| 66. 加一 | 翻轉一下會比較方便 |
| 67. 二進制求和 | 同樣reverse一下比較方便 |
| 73. 矩陣置零 | 遇到0就把行列都標記成一個負數,最后全都改成0 |
| 75. 顏色分類 | 遍歷了兩遍 |
| 80. 刪除排序數組中的重復項 II | 記錄一下出現次數就好 |
| 83. 刪除排序鏈表中的重復元素 | 模擬題,如果當前數值和下一個數值相同,就刪除下一個節點 |
| 87. 擾亂字符串-有點難 | 這道題也不知道是啥算法。兩個字符串首先排序之后要相等。有兩種情況。1.a[0,i] = b[0,i], a[i, n]=b[i,n]。或者a[0,i] = b[n-i, n], a[n-i, n]=b[0, i]。枚舉每個分界點,然后遞歸處理這兩種情況就行。 |
| 89. 格雷編碼 | 這個,比較套路 |
| 128. 最長連續序列 | 先把所有數據放入set中。遍歷每個數,如果沒有比這個數小1的數,就一直找比他大1的數。統計連續數列的長度。內層雖然有一個while循環,但是內層while循環總數不會超過n次。所以也是O(N)的算法 |
| 163. 缺失的區間 | 就是使用nums里面的數切割lower到upper這個區間。注意會溢出 |
| 165. 比較版本號 | 一個一個比較,如果相等要設置為0。 |
| 166. 分數到小數 | 這道題主要是模擬除法。并且記錄商在結果的什么位置。如果商重復了,說明循環了,在記錄的位置處加上括號,最后也加上閉括號,直接返回。 |
| 169. 多數元素 | 經典題目 |
| 171. Excel表列序號 | 26進制轉10進制 |
| 189. 旋轉數組 | 三次旋轉 |
| 202. 快樂數 | 這是一道模擬題。中間產生的數字全都記錄一下,如果出現重復了,就說明出現重復了,直接返回false |
| 205. 同構字符串 | 把兩個字符串全都映射成從1開始的字符串。然后對比s和t是不是相同就好 |
| 238. 除自身以外數組的乘積-挺好 | 如果能用除法就很簡單了。不讓用除法,就來兩邊,第一次從左到右,ret[i] = mul(a[0, i - 1])。第二次從右到左,ret[i] *= mul(a[i + 1, n]). |
| 242. 有效的字母異位詞 | 排序看看是不是一樣的就好 |
| 258. 各位相加 | O(n)的算法 |
| 263. 丑數 | 查看一個數是不是只有2,3,5這三個因子 |
| 264. 丑數 II | 有點想三路歸并,不過三個序列是相同的。i2,i3,i5指向2,3,5包含這三個因子的最小的數。每次用i2,i3,i5指向的數和2,3,5生成最小的數,下一個最小的數肯定從這三個數里面產生,如果產生了,則對應的指針++。 |
| 273. 整數轉換英文表示 | 要抓住幾個關鍵點,分別是20,100,1000,一百萬,一個億。一百一下的要特殊處理。二十一下的也要特殊處理。如果等于0就直接返回,如果小于20就返回對應單詞,如果小于100就返回對應單詞,各位數遞歸處理。否則,從大到小處理,數字除以關鍵點的商遞歸處理,然后加上關鍵點的單詞。剩下的數據遞歸處理。 |
| 290. 單詞規律 | 模擬題,可以用map記錄字母和單詞的對應關系 |
| 299. 猜數字游戲 | 模擬題 |
| 313. 超級丑數 | 題目給了很多個質數,所以只好用小頂堆(要重載 > )把所有質數放入堆中,每次取堆頂元素(堆頂可能有多個相同),然后把新的值再加入堆中就好。 |
| 334. 遞增的三元子序列 | 用兩個變量記錄最小的兩個元素,如果有一個數比次小元素都大,說明有遞增三元組 |
| 335. 路徑交叉 | 這道題著實有點鬼畜 |
| 336. 回文對 | 這道題還挺好的。首先把所有字符串都reverse并加入map中。然后遍歷所有單詞,將單詞分為left+right兩部分,如果right是回文的,reverse(left)存在,并且reverse(left)的序列號不是當前單詞就說明是一個回文對。corner cases是“”,如果有“”,上面的算法只能處理 回文+“”的情況,不能處理 “”+回文的情況。后面這種情況要單獨處理。 |
| 345. 反轉字符串中的元音字母 | 先把元音字母拿出來,再逆序放回去 |
| 385. 迷你語法分析器 | 對于每種情況分別考慮。【就新建一個對象,放入棧頂。】拿出棧頂元素,如果有數字就把數字加入,如果棧空了就直接返回,否則把當前對象加到棧頂里面。如果是,把數字加入棧頂。如果是數字就用tmp記錄一下。 |
| 388. 文件的最長絕對路徑 | 這道題比較方便的是制表符就是文件的層次。所以先用換行符切割,然后計算制表符個數。用一個棧記錄之前所有文件夾的長度。如果棧的size大于制表符個數了,就要pop。然后記錄當前的長度。如果當前字符串有.就說明是一個文件了,就嘗試更新長度。記住一個方法 getline(stringstream, string, delimiter(char)). |
| 391. 完美矩形 | 遍歷所有矩形。并遍歷每個點。如果某個點出現過,就刪除。同時統計所有小矩形的面積。最后看看是不是只剩4個點。并且四個點組成的面積和統計的小矩形的面積一樣 |
| 394. 字符串解碼 | 需要記錄重復次數和字符串。用棧記錄(replica,str)。如果掃描到數字,就加到replica中。【就使用replica加入新建node,加入棧頂。】pop出棧頂,重復replica次字符串,如果此時棧為空,就把結果加到ret中,否則把結果放入棧頂字符串。如果是字符串。如果此時棧空,就直接加到ret中,否則加到棧頂字符串。 |
| 401. 二進制手表 | 遍歷所有情況,保留數字個數相同的情況。 |
博弈論
| 292. Nim 游戲 | 1,2,3是必贏局面。4是比輸局面。所以只要%4不為0,就是必贏局面。 |
設計題目
| 146. LRU緩存機制 | 這道題很不錯。數據考慮放在可以O(1)修改的數據結構里。數據就放在list中。至于key對應的數據在list的什么地方,就用一個map存儲。get的時候,從map里找一下有沒有這個數據,如果有就用迭代器返回數據,并使用emplace_front把當前數據O(1)的放到最前面。put的時候,在map里找一下數據,找到了就更新數據,并放到list最前面。沒找到,如果已經滿了,就刪除list最后的數據,然后把數據放入list頭部。 |
| 170. 兩數之和 III - 數據結構設計 | 哈希表存儲所有數據。find的時候最壞會遍歷整個哈希表。 |
| 173. 二叉搜索樹迭代器 | 暴力做法就是直接遍歷一遍。(因為next要常數時間,還沒有fathre指針) |
| 223. 矩形面積 | 算出上下左右的邊界,然后用兩個面積減去重疊的面積。 |
| 224. 基本計算器 | 這道題有括號。遇到(就先把結果和符號壓入棧中。如果遇到)就先把臨時結果加到結果中,然后再乘棧中的符號,再加上棧中的結果。 |
| 227. 基本計算器 II | 這道題只有加減乘除。乘除優先級比加減高。所以記錄上一個數字last。如果是乘除,n = last * n or last / n。因為優先級比較高。所以要ans要減去之前的數據last,然后再加上新結果n。ans=ans - last + n |
| 232. 用棧實現隊列 | 用兩個棧模擬,一個進,一個出。 |
| 284. 頂端迭代器 | 用一個隊列緩存peek的數據 |
| 287. 尋找重復數 | 可以排序,或者根據鴿籠原理原地交換 |
| 341. 扁平化嵌套列表迭代器 | 這道題還挺巧妙。主要就是要記錄每個list的begin和end迭代器。hasNext是關鍵。這個函數要把begin的迭代器指向第一個數字。如果begins和ends兩個棧top相同,說明一個list走到頭了。就pop掉。如果begins的top不是數字,說明是列表,把當前棧頂移向下一個位置,同時把列表的begin和end押入棧中。 |
| 380. 常數時間插入、刪除和獲取隨機元素 | 刪除元素的時候,把元素和vector最后一個數字交換,然后pop_back。 |
| 381. O(1) 時間插入、刪除和獲取隨機元素 - 允許重復 | 記錄數組坐標的時候記錄多個就好,刪除的時候隨便刪一個 |
數學推公式
| 172. 階乘后的零 | 階乘的那些數字里,一對因子2和5就會產生一個0。因子2的數量肯定比因子5的數量多。所以只需要算5的數量。5每5個出現一次。25每25出現一次。 |
| 204. 計數質數 | 線性篩質數。 |
| 233. 數字 1 的個數 | 數位統計,一位一位算就好 |
| 268. 缺失數字 | 所有數都知道,就求個和,然后把有的數減去,剩下的就是少的那個數據。 |
| 319. 燈泡開關 | 最后結果是開方。。有點扯 |
| 321. 拼接最大數 | 從a中挑選k個,b中挑選n-k個。a中的k個一定是a里面最大的k個數。然后挑選出來的數組成一個新的數字,保留最大的一個。沒有所有可能的k就好。 |
| 326. 3的冪 | 是否只有3這個因子 |
| 342. 4的冪 | 是否只有4這個因子 |
| 357. 計算各個位數不同的數字個數 | 可以一位一位算。一位數有A(9,1)中選擇。兩位數有A(9,2)+A(9,1)中選擇。i位數有A(9,i) + (i-1)A(9, i -1)。A(9,i)中沒有考慮有0的情況。(i-1)A(9, i - 1)中考慮了有0的情況(0也不能重復,所以只需考慮一個0的情況)。 |
| 367. 有效的完全平方數 | i*i <= num, 或者i <= num / i 。后面一種請款不會爆int,但是要判0。 |
| 372. 超級次方 | a^(abc) = a(100a)a(10b)a?。 |
| 382. 鏈表隨機節點 | 蓄水池抽樣(原理不太懂)。讓 cnt 遞增。如果rand() % cnt == 0就取當前的數。 |
| 384. 打亂數組 | 洗牌算法,遍歷每個數,嘗試交換當前數和后面某個數。后面數字的 index=i + (rand() % (n - i)) |
| 396. 旋轉函數 | f(0)=0A0 + 1A1 + (n-1)An-1. f(1) = 0An-1 + 1A0 + … + (n - 1)An-2. f(i) = f(i - 1) + sum - n A[n - i] |
| 397. 整數替換 | 歐樹的時候直接移為。奇數的時候,如果減1后的1比加一后的1多,就減一(n=3的時候也減一,這是特例。。) |
| 398. 隨機數索引 | 蓄水池抽樣,遍歷一遍所有數字。用cnt記錄遇到target的個數。每次j=rand()/cnt, 如果j等于0,就選取這個坐標。這保證每個target遇到的概率最后都是1/cnt |
| 400. 第N個數字 | 先算有幾位,1位有9個。兩位有90個。。。。算出有幾位之后,再算是什么數。(n-1)/ len,就是剩下的數除以位數。然后在數的第(n-1)%len就是結果。 |
總結
以上是生活随笔為你收集整理的leetcode题目总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Bean初始化过程
- 下一篇: DiskSim