LEETCODE 刷題記錄

文章目錄

島嶼問題

在由一片0組成的海洋中,飄着由1組成的陸地(此處0和1可以替換爲任何兩個不同的符號)。針對島嶼有着一系列問題:

200. Number of Islands

最基礎的是這片海上有多少個島嶼?
DFS或者BFS都可以做,個人感覺DFS更好寫一點。
代碼:Number of Islands I

305. Number of Islands II

這次初始是一片海洋,題目會給一組座標作爲每次新增加的陸地。求每次增加陸地後的島嶼數。
暴力解法完全可以執行N輪問題200中的代碼,但是這樣的效率是很低的。因此需要用到一種常見的算法:並查集(Union Find)
給定一些點與點之間聯通的情況,判斷哪些點屬於一個組中,不需要具體路徑的時候,使用並查集就是比較好的。爲了性能考慮我們採用帶權值的樹結構來存儲點和羣組。
代碼:Number of Islands II

694. Number of Distinct Islands

在不考慮旋轉映射等情況下,這片海上有多少個不同的島嶼呢?
在 Number of Islands基礎上,只需要儲存節點相對位置即可:
代碼:Number of Distinct Islands

711. Number of Distinct Islands II

接着694問,如果此時考慮旋轉等情況,這片海上又有多少不同的島嶼呢?
這個主要的問題在於如何建模,使得旋轉鏡像的圖形都屬於同一類。這個我參考了網上代碼,思路是:
對694中得到的節點位置進行normalize,目的是變換成同一種島嶼形狀的唯一表示。
對於每一個座標位置,其實總共有8種變換可能:x和y都可以分別變爲相反數,且也可以同時變爲相反數,再加上其本身,這就4種了。同時,上面的每一種情況都可以交換x和y的位置,這樣總共就有8中變換方法。
使用8個大小相同的數組來保存各自所有的點。對於每一種形狀,都對其所有的點進行排序,然後將每個點的絕對座標變爲相對座標,即每個點都減去排序後第一個點的座標,最後再對這8個形狀排個序。
只要是屬於同一個島嶼的形狀,最後都會得到一模一樣的8個形狀數組,爲了簡單起見,只選取第一個形狀形狀當作這同一種島嶼的模型代表。
代碼:Number of Distinct Islands II

迴文數問題

迴文數是一個比較麻煩的處理點,性質是從前往後讀和從後往前讀的結果相同。

234. Palindrome Linked List

這是一個將回文數和鏈表結合起來的問題。可以用快慢指針找到中點,然後翻轉後半鏈表去比較,完事將鏈表還原。

131. Palindrome Partitioning

這個的思路是順位從開始到結尾判斷是否是迴文數,是則加入最後的表中
Palindrome Partitioning

132. Palindrome Partitioning II

與131不同,這次不需要給出全部的分割法,只需要給出需要分割的最小次數。
碰到類似的題,優先考慮DP。
思路是:
Palindrome Partitioning II

1246. Palindrome Removal

給出一個數組,最少刪除幾次就可以全部刪完。如果有回味序列刪一次就可以。
區間dp。主要是遞推公式,見遞推公式
Palindrome Removal

5. Longest Palindromic Substring

這個的思路是記錄出現過的最長的迴文數的位置和長度,同樣是從0開始擴展。思路是尋找重複的單元找到重複單元兩側向外擴展尋找回文。
Longest Palindromic Substring

906. Super Palindromes

一個數當他自身是迴文數,同時它的平方根(是整數)也是迴文數的時候,我們稱爲超級迴文數。求給定範圍內的超級迴文數。
回溯法應用,思路不是通過判斷而是通過構造來找出滿足的例子。
Super Palindromes

括號問題

涉及到左右括號匹配等一系列問題

22. Generate Parentheses

給出括號對數N,求出所有的有效表達式。
思路是記錄有多少左括號,直到記錄的括號數爲0,然後類似回溯法生成即可。
Generate Parentheses

32. Longest Valid Parentheses

給出一個括號組成的string,找出最長的有效的括號對的長度。
利用一個棧來存儲括號對應的pos,然後彈出匹配成功的段。最後利用一個循環確定最長的子串。
Longest Valid Parentheses

301. Remove Invalid Parentheses

給出一段括號字符串,移除最少的括號使得該字符串左右括號匹配。
思路是DFS,對每一個字符做加入或者不加入的判斷,最終將結果保存在set中即可。
Remove Invalid Parentheses

跳跳樂問題

給定一個非負整數數組,最初定位在數組的第一個索引處。
數組中的每個元素表示該位置的最大跳轉長度。以此衍生的一系列問題。

55. Jump Game

判斷是否能夠到達最後一個索引
用一個reach記錄當前可以到達的最遠距離,當i>reach意味着沒辦法從之前的路徑到達之後的節點,所以認爲是跳不過去。
jump game

45. Jump Game II

求從開始到結束最少跳幾次
與之前的問題類似,也是採用一個記錄當前到達的點最多是多少
jump game II

旋轉的排序數組問題

一個排好序的數組,從某一個點切開旋轉,得到的就是 Rotated Sorted Array。舉例:[1,2,3,4,5]從3切開,得到[4,5,1,2,3]。以此衍生了一些問題。

33. Search in Rotated Sorted Array

給定要搜索的目標值。 如果在數組中找到則返回其索引,否則返回-1。
假設數組中不存在重複。算法的運行時複雜度必須爲O(log n)。
這個思路很清晰,首先通過二分法找到旋轉點,獲得旋轉點以後,我們可以以旋轉點爲offset取餘,這樣對我們來說,這個數組就和旋轉前的數組沒區別了。
Search in Rotated Sorted Array

81. Search in Rotated Sorted Array II

您將獲得要搜索的目標值。 如果在數組中找到則返回true,否則返回false。
與33題不同的地方在於,這次的問題中數組是包含重複的元素的,也就是說在二分法處理問題的時候我們需要額外判斷一種情況:left=mid=right。其他沒有變化,時間複雜度爲O(logN)
Search in Rotated Sorted Array II

153 Find Minimum in Rotated Sorted Array

無重複元素的旋轉排序數組找最小值。33中找到的rot就是最小值

154 Find Minimum in Rotated Sorted Array II

和153同理,只不過額外判斷當nums[mid] == nums[high]的情況
Find Minimum in Rotated Sorted Array

方陣中尋找最大面積問題

給出一個包含01的矩陣,判斷裏面最大的矩形的面積

85. Maximal Rectangle

DP問題,思路是分別用三個數組記錄當前位置的高,左起始和右起始。最後算出來最大的區域面積。
Maximal Rectangle

221. Maximal Square

問題類似於上面的矩陣問題,只不過換成了求最大正方形面積。只需要在原代碼基礎上在最後計算面積時選擇pow(min(right[i] - left[i], height[i]), 2);

Single Number 問題

Single Number I II:

一個int數組中,每個數都出現了k(k>1)次,其中有一個元素出現p(p>=1 && p%k != 0)次。求找出這個元素。

這類型的題在評論區有位大佬有總結,我把它翻譯過來如下:

  1. 首先考慮特殊情況:只有一位bit
    爲了統計數組中1出現的次數,我們需要一個m位的計數器。這個技術器有以下的性質:
    計數器有一個初始值,爲了簡單起見,置爲0;
    對於數組中的每個輸入,如果爲0,計數器保持不變;
    對於數組中的每個輸入,如果爲1,計數器加1;
    爲了保證計數器表示的值能大於等於k,所以2m2^m >= k,等式兩邊取對數:m >= logk。
    注意位操作與0進行運算時不會改變自己:x = x | 0 和x = x ^ 0
    xm要改變值的條件是,xm-1, …, x1和i都爲1,對應的算術表達式爲:xm = xm ^ (xm-1 & … & x1 & i)。沒錯,這就是我們找到的位操作方法。
    當計數器等於k時,我們需要一種重置機制把計數器重置爲0。爲了達到這個目的,我們申請一個變量mask,分別對計數器的每一位(xm, …, x1)和mask進行按位與操作,即xm = xm & mask, …, x1 = x1 & mask。如果我們能保證,只有當計數器的值等於k,並且統計的都是數組元素爲1情況下,mask會爲0,我們就達到了目的。
  2. 其次考慮一般情況:32bit的整數
    他們能“共同”管理這32個計數器。說是“共同管理”,是因爲m的最小值滿足m >= logk時,我們可以用m個32位的整數代替32個m位的計數器。
  3. 返回值
    返回什麼值,現在已經很明顯了,用二進制形式表示p’ = p % k,當pjp'_j = 1時,返回xjx_j即可。總結起來,算法的時間複雜度爲O(n * logk),空間複雜度爲O(logk)。
    Single Number

Single Number III

這次是其中有兩個元素出現了1次,其他都是出現兩次。
代碼邏輯如下:假設a,b是所求元素
首先通過^ 得到 r = a^b
a^ b的本質是保留了a,b中不相同的位保留下來。通過 r &(~(r-1))得到最右邊1的位置,這個就可以把a,b分在不同的陣營。分別再做一次 ^ 得到最終結果。
single number III

圖問題

133. clone graph

關於BFS和DFS的最基本的應用。
Clone Graph

207. Course Schedule

參加n門課程,課程之間有依賴關係(有向圖),判斷該有向圖是否有環。

兩種解決方案:
BFS:方法是重複尋找一個入度爲0的頂點,將該頂點從圖中刪除(即放進一個隊列裏存着,這個隊列的順序就是最後的拓撲排序,具體見程序),並將該結點及其所有的出邊從圖中刪除(即該結點指向的結點的入度減1),最終若圖中全爲入度爲1的點,則這些點至少組成一個迴路。

DFS:假設圖以鄰接矩陣表示,一條深度遍歷路線中如果有結點被第二次訪問到,那麼有環。我們用一個變量來標記某結點的訪問狀態(未訪問,訪問過,其後結點都被訪問過),然後判斷每一個結點的深度遍歷路線即可。

Course Schedule I

210. Course Schedule II

您必須參加總共n門課程,標記爲0到n-1。
有些課程可能有先決條件,例如,要修課程0,你必須先修課程1,表示爲一對:[0,1]
根據課程總數和先決條件對列表,返回完成所有課程所需的課程順序。
只需要將入度爲0的節點輸出到數組中即可。

有限狀態機

289. Game of Life

給定具有m×n個單元的矩陣,每個單元具有初始狀態live(1)或dead(0)。每個單元格使用以下四個規則與其八個鄰居(水平,垂直,對角線)進行交互:

  1. 任何活着的單元如果鄰居少於兩個的活單元就會死亡,由於人口不足造成的。
  2. 任何有兩個或三個活着的鄰居的活單元都會繼續活在下一代。
  3. 任何有三個以上活着的鄰居的活單元都會死亡,由於人口過多。
  4. 任何具有正好三個活鄰居的死單元變成活單元,這是通過繁殖。

編寫一個函數來計算給定其當前狀態的矩陣的下一個狀態(在一次更新之後)。通過將上述規則同時應用於當前狀態中的每個細胞來創建下一個狀態,其中出生和死亡同時發生。
要求原址操作。
這類問題可以採用有限狀態機方式,同時保存舊的狀態和新的狀態來實現原址操作。
game of life

65. Valid Number

判斷一個字符串是不是合法的數字表達式,DFA。
valid number

二叉樹問題

二叉樹是每個結點最多有兩個子樹的樹結構。圍繞二叉樹會衍生出一系列問題

103.Binary Tree Zigzag Level Order Traversal

給定二叉樹,返回其節點值的Z字形級別遍歷。 (即,從左到右,然後從右到左進行下一級別並在之間交替)。
我給出的解法是,先把每一層輸出出來,然後對奇數層的vector做一個reverse。討論區給了一種更直接的方法,採用一個隊列保存節點,彈出的時候則判斷是應該正向輸入還是逆向輸入。
Binary Tree Zigzag Level Order Traversal

236. Lowest Common Ancestor of a Binary Tree

給出一個二叉樹,找出所給兩個節點的最小公共祖先(LCA)
有個關鍵的特性:如果待尋找的兩個點出現在不同的子樹中,那麼當前節點就是我們要的最終結果。簡化後的代碼如下:
Lowest Common Ancestor of a Binary Tree

337. House Robber III

二叉樹搶劫,不能搶劫相鄰的節點(比如父節點和他的子節點),求能搶劫的最大錢數。
保存帶上根節點的最大值和不帶根節點的最大值即可。
House Robber III

95. Unique Binary Search Trees II

給定整數n,生成存儲值1 … n的所有結構上唯一的BST(二叉搜索樹)。
可以通過深度優先搜索(遞歸)解決這道題。
因爲二叉查找樹滿足父節點的值大於左子節點的值,小於右子節點的值,所以我們可以:
(1) 從 N=1 開始構建二叉查找樹,則它的左子樹節點數爲 0,右子樹節點數爲 n-1;
(2) N=2 時,左子樹節點數爲 1,右子樹節點數爲 n-2;
……
(n) N=n 時,左子樹節點數爲 n-1,右子樹節點數 0。
而在第(1)步中,右子樹繼續執行上述循環,子樹的子樹又執行這個循環,最終,我們可以將子樹節點數減少到 1,而一個節點只有一種排列方式,所以此時可以毫不猶豫地將結果返回給上一級。然後包含有兩個節點的二叉樹排列方式又被返回給上一級。……
依此類推,我們最後可以得到所有不同結構的二叉查找樹。
Unique Binary Search Trees II

99. Recover Binary Search Tree

二叉搜索樹中兩個元素對調了,在不改變結構的情況下,糾正回來。
學習一下Morris Traversal
思路如下:
BST中序遍歷是升序,當出現降序時,說明是被交換了。
Recover Binary Search Tree

428. Serialize and Deserialize N-ary Tree

序列化與反序列化樹。聯動問題:297 序列化與反序列化二叉樹。
N叉樹的一個序列化方法是用括號表示當前節點的子樹。
反序列化則是利用棧來還原樹。
Serialize and Deserialize N-ary Tree

中位數問題

4. Median of Two Sorted Arrays

很簡單的思路:保證分出來的兩部分一樣多的情況下(分割數組1的i固定,意味着分割數組2的j固定),判斷是否滿足中位數要求(中位數本質:給出一個劃分,使得左右兩邊都小於(或大於)這個劃分)。
findMedianSortedArrays

鏈表問題

148. Sort List

排序鏈表, O(n log n) 時間複雜度,O(1)空間複雜度。
只有一點,雖然想到歸併排序的方法,但是把歸併過程想複雜了,在討論區看到一個簡潔的歸併,代碼如下:
sort list

23. Merge k Sorted Lists

合併K個已排序列表,用優先隊列來輔助。
Merge k Sorted Lists

25. Reverse Nodes in k-Group

K個一組來翻轉鏈表,找到長度爲k的節點後,記錄對應的節點,翻轉當前節點,向下一個節點繼續做同樣的處理方法。
Reverse Nodes in k-Group

鏈表求和,分爲正序存放和逆序存放

逆序存放就是按部就班加起來,最後別忘了進位要新建一個節點。
正序則是利用棧來輔助。

單詞問題

Word Ladder

給定兩個單詞(beginWord和endWord)和一個字典的單詞列表,找到從beginWord到endWord的最短變換序列的長度,滿足:

  • 一次只能更改一個字母。
  • 每個轉換後的單詞必須存在於單詞列表中。 請注意,beginWord不是轉換後的單詞。

注意:

  1. 如果沒有這樣的轉換序列,則返回0。
  2. 所有單詞都有相同的長度。
  3. 所有單詞僅包含小寫字母字符。
  4. 您可以假設單詞列表中沒有重複項。
  5. 您可以假設beginWord和endWord是非空的並且不相同。

這個題思路上來說是比較簡單的,雙向BFS。理論上也是可以用DFS,但是可能會超時。
Word Ladder
在I的基礎上,輸出所有長度最短的序列。
同樣是BFS的應用。具體分析註釋在代碼中。
Word Ladder II

Word Search

給一個2維的字母矩陣,判斷所給的單詞數組中哪些單詞能夠通過字母矩陣生成。
I 判斷word是否能被字母矩陣生成,回溯法即可。
II 給一個單詞列表,找出所有能被生成的單詞。trie的應用是爲了能夠讓擁有相同前綴的string在判斷到達根節點以後同時加入到set。這個相比暴力的搜索法在擁有更多相同前綴的string時,效率要高得多。
Word Search II

Word Break

給定一個非空字符串 s 和一個包含非空單詞列表的字典 wordDict,判定 s 是否可以被空格拆分爲一個或多個在字典中出現的單詞。
I 只需要判斷能否切割。這個時候使用動態規劃即可解決。
II 在 I 的基礎上需要輸出所有字符串的拆分方式
思路是:首先用一個hash表儲存給定的字典wordD,構造一個hashmap用來儲存當前字符串長度和輸出字符串memo。構造一個函數dp。核心思想是通過動態儲存來減少重複計算的浪費。
word break II

買賣股票問題

原問題

買賣股票的問題在leetcode上一共包含六個。問題分別描述如下:
每個題目都會給一個數組,其中第i個元素是第i天給定股票的價格。
121:購買之前必須出售股票。每天只允許完成一筆交易,求最大利潤
122:購買之前必須出售股票。儘可能的進行交易,求最大利潤
123:購買之前必須出售股票。最多能進行兩次交易,求最大利潤
188:購買之前必須出售股票。最多能進行k次交易,求最大利潤
309:購買之前必須出售股票。儘可能的進行交易,但是賣出後的一天內不能交易,求最大利潤。
714:條件和122相同,但是每次完成交易都需要付一筆交易費fee,求最大利潤

心得

121,122,123,188其實是同一個問題的不同形式。其中以188是一般問題,121是k=1的情況,122是k=\infty的情況,123則是k=2的情況。
先看一般問題的解法:

首先這個問題使用DP的核心表達式(子問題)爲:

dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1] + prices[i])
              max(   選擇 rest  ,           選擇 sell      )
解釋:今天我沒有持有股票,有兩種可能:
要麼是我昨天就沒有持有,然後今天選擇 rest,所以我今天還是沒有持有;
要麼是我昨天持有股票,但是今天我 sell 了,所以我今天沒有持有股票了。
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0] - prices[i])
              max(   選擇 rest  ,           選擇 buy         )
解釋:今天我持有着股票,有兩種可能:
要麼我昨天就持有着股票,然後今天選擇 rest,所以我今天還持有着股票;
要麼我昨天本沒有持有,但今天我選擇 buy,所以今天我就持有股票了。

base case:
dp[-1][k][0] = dp[i][0][0] = 0 
//第i天沒做交易,或者還沒開始計時(第-1天),此時手上沒有股票,利潤都是0。
dp[-1][k][1] = dp[i][0][1] = -infinity 
// 第i天沒做交易,或者還沒開始計時(第-1天),此時手上有股票,不可能,用負無窮表示。

309的問題是在122的基礎上,增加了每次購買之後需要冷卻一天的要求。這使得基本的子問題稍微發生變化,在hold的時候,當第i天想要購買是,減去的是i-2天的hold值。
714則是在122的基礎上加了交易費,每次賣出時加一筆費用。
Best Time to Buy and Sell Stock

單調棧問題

84. Largest Rectangle in Histogram

給出一系列不同高度的矩陣,求最大面積。
這個是一個單調棧思路,維護一個只保存一路遞增的棧,在處理棧中元素時就能保證最大面積在其中。詳細講解和演示見這裏
Largest Rectangle in Histogram

基本計算器

實現基本計算器來評估簡單的表達式字符串。

224. Basic Caculator

表達式字符串僅包含非負整數,+, - 運算符和空格,左右括號。 整數除法應截斷爲零。

227. Basic Calculator II

表達式字符串僅包含非負整數,+, - ,*,/運算符和空格。 整數除法應截斷爲零。

772. Basic Calculator III

表達式字符串僅包含非負整數,+, - ,*,/運算符和空格,左右括號。 整數除法應向下截斷。

我的解法是用到了stringstream,term 負責計算兩個加減號之間的所有乘法的值,並在下一次讀到加減號時,把結果加減在total上。括號則是按照棧來匹配每次調用子函數來計算括號中的內容,並返回結果修改原字符串。
227 是最基礎的計算,不包含括號,可以直接用caculate_help解決。
224 是在227的基礎上,只包含±,帶括號,可以把主函數的乘除部分刪去。
772 就是224 和 227 的合併。
代碼:
Basic Calculator

另一種解法是依賴棧和運算符優先級解決,代碼不放了。

滑動窗口

滑動窗口的共性:

  1. 窗口由兩個指針構成,一個左指針left,一個右指針right,然後[left,right]表示的索引範圍是一個窗口了。
  2. 右指針right的功能是用來擴展窗口:當窗口內的條件沒有達到題目要求時,我們需要不斷移動右指針right直到窗口內的條件第一次滿足題目要求爲止。
  3. 左指針left的功能是用來縮小窗口的:當窗口內的條件已滿足題目條件或多於題目條件時(窗口溢出),我們縮小窗口,也就是左指針left需要右移直到窗口條件不滿足爲止。這時,我們需要記錄當前窗口的大小,並更新目前爲止滿足條件的最小窗口記錄。之後,再次擴展右指針right,使得窗口滿足題目的條件。

76. Minimum Window Substring

給出字符串S和T,找出S中包含T中全部字母的最小子字符串。
類似問題,需要一個數組記錄目標的變化情況,並將每次達到要求的子串長度和其實位置記錄下來,這個count就是精髓
Minimum Window Substring

424. Longest Repeating Character Replacement

給你一個僅由大寫英文字母組成的字符串,你可以將任意位置上的字符替換成另外的字符,總共可最多替換 k 次。在執行上述操作後,找到包含重複字母的最長子串的長度。
Longest Repeating Character Replacement

239. Sliding Window Maximum

詳細解釋見代碼
Sliding Window Maximum

其他未歸類問題

395. Longest Substring with At Least K Repeating Characters

查找給定字符串的最長子字符串T的長度(僅由小寫字母組成),以便T中的每個字符出現次數不少於k次。
思路是這樣的:逐位去尋找是否有合適的子串,並在找的過程中記錄出現過的最大子串長度,如果找到了一個子串則沒有必要檢查它覆蓋的子串。代碼如下:
Longest Substring with At Least K Repeating Characters

347. Top K Frequent Elements

給一個非空的數組,求按照頻率排序下來的前k個元素
我所首先想到的思路是優先隊列,C++中priority_queue的使用。
看了討論區的解答後,還發現一種比較好用的方法,桶排序:
Top K Frequent Elements

312. Burst Balloons

通過戳爆所有的氣球,來獲得最大硬幣和。
只需要掌握一點:選擇一個氣球不戳爆,以他爲分割點,左右兩個序列是相互獨立的。也就是說一個首位爲I和J的序列,以中間爲K的點分割,則該序列的最大值爲:
max[I][J] = nums[I-1]*NUMS[K]*nums[J+1] + max[I][K-1] + max[K+1][J]
以這個作爲動態規劃的公式:
Burst Balloons

416. Partition Equal Subset Sum

給出一系列非負整數,求問他們能不能分成大小相同的兩個組。比如[1,5,5,11]可以分成[1,5,5]和[11]
我的方法超空間了,記錄討論區一個大佬的解法:
用到了bitset作爲數據結構,bitset裏面有對這個結構的簡單介紹。
通過移位操作記錄之前每個數加了多少,在和自身或操作。bitset每一位代表是否能夠取到對應位置的和。最後只需要看能不能找到所求值即可。這裏說明的更加詳細
Partition Equal Subset Sum

560. Subarray Sum Equals K

給出一個數組,和整數k,求有多少個連續的子序列的和等於k
基本思路:如果累計總和,在索引 i 和 j 處相差 k,即 sum[i] - sum[j] = k,則位於索引 i 和 j 之間的元素之和是 k。

基於這些想法,可以使用了一個哈希表 unordered_map,它用於存儲所有可能的索引的累積總和以及相同累加和發生的次數。我們遍歷數組nums並繼續尋找累積總和。每當我們遇到一個新的和時,我們在hashmap中創建一個與該總和相對應的新條目。如果再次出現相同的和,我們增加與map中的和相對應的計數。此外,對於遇到的每個總和,我們還確定已經發生 sum-k總和的次數,因爲它將確定具有總和 kk的子陣列發生到當前索引的次數。我們將 count增加相同的量。
最終count就是結果
Subarray Sum Equals K

48. Rotate Image

in-place旋轉圖像。先reverse數組在對位交換,很巧妙。注意reverse一個二維數組只會反正高維,不會反轉低維。
Rotate Image

300. Longest Increasing Subsequence

給出一個未排序的數組,找出最長增長子序列的長度
我們給出三個策略判斷增加一個已存在的序列是否是安全的

  • 如果A[i]是所有lists中最小的,則開一個新的list,長度爲1
  • 如果A[i]是所有lists中最大的,則擴展已有的lists
  • 如果不是以上兩種情況,則clone並擴展所有最後一個元素小於A[i]的lists,同時銷燬和擴展後lists同長度的lists

當計算最大長度時,則只需要計算末尾的元素即可。
Longest Increasing Subsequence
該問題可以聯動類似題目334. Increasing Triplet Subsequence

324. Wiggle Sort II

給定一個未排序的數組nums,重新排序,使得nums [0] < nums [1] > nums [2] < nums [3] O(N)時間和/或O(1)額外空間

這個問題如果不考慮附加條件比較簡單,只需要先排好序然後大小混着填即可。考慮到O(n)的時間複雜度和常量級別的空間複雜度就比較困難了。我看到評論區裏面有人給出了一種基於“虛擬index”思想的方法。
這個方法的思路是首先利用nth_element找到中位數,然後#define A(i) nums[(1+2*(i)) % (n|1)]很巧妙,把給定數組按照先奇數後偶數的方式對應起來,
然後通過交換方法讓左邊的奇數位全部都是大於median的數,右邊則全部是小於median的數,這樣相應的原來的數組中順序就是wiggle的。可以說是很巧妙了。
Wiggle Sort II

179. Largest Number

給定一個非負整數列表,將它們排列成最大數字。
我一開始的想法是利用基數排序,對於高位相同的數來說,位數少的優先,但這樣實現起來很複雜,討論區給出了一種簡單的方法。其實思路很簡單,不對數字排序,而是對轉化後的字符串排序,利用sort函數 自己寫一個比較器,這樣會簡潔的多。
Largest Number

15. 3Sum

給定n個整數的數組nums,是否有元素a,b,c在nums中,a + b + c = 0? 找到數組中所有唯一的三元組,它們的總和爲零。
解決方案集不得包含重複的三元組。

這個問題,我一上來準備使用暴力方法,利用multiset解決重複問題,顯然時間複雜度爲O(N3N^3)是行不通的。因此評論區給了一個方法,思路是:先對數組進行排序,排好序之後再固定一個元素的情況下,分別從前後兩端開始查找。
3sum

43. Multiply Strings

給出兩個用字符串表示的數字,返回用字符串表示的這兩個數字的乘積。
關鍵的一點:當前位置可以由序號和相同的乘法加起來決定的。
Multiply Strings

54,59 spiral matrix

這兩個問題都是螺旋矩陣的問題,對於這類問題的處理有一個通用的解法。這裏將59的代碼放下面:
spiral matrix

89. Gray Code

格雷碼是二進制數字系統,其中兩個連續值僅在一位上不同。
給定代表代碼中總位數的非負整數n,打印格雷碼序列。 格雷碼序列必須以0開頭。
問題的突破點在於格雷碼生成特性:輸入爲n的格雷碼,後2n12^n-1元素的值 = 前2n12^n-1的元素的值的逆序 + 2n12^{n-1}
Gray Code

42. Trapping Rain Water

給一個N個非負元素的數組,代表高度,求下雨時能積多少水。

其實該問題還有別的解決思路,也就是積累法:分別維護一個maxleft和maxright,將整個池子想象成一個大的水池,不斷擡高邊界高度即可。
Trapping Rain Water

128. Longest Consecutive Sequence

給一個亂序數組,找到其中連續最長的序列的長度。比如[100,2,65,1,3],結果是3([1,2,3])。複雜度O(N)

這個問題我想的沒問題,但是寫起來的時候空間用多了,導致修改了很久。核心的思想是:維護一個哈希表unordered_map,用來記錄數組中的數和對應的最大連接長度。只需要維護最長連接數組的兩端即可。
Longest Consecutive Sequence

218. The Skyline Problem

給出一系列長方形的起始座標,終點座標和高度,獲得整個圖形的輪廓座標。
方法是描線法。將端點分爲左右兩個端點處理,每當最大高度不同時,即爲轉折點,保存下來。具體分析見代碼。
The Skyline Problem

57. Insert Interval

給定一組非重疊間隔,在間隔中插入新間隔(必要時合併)。
分析見代碼註釋。
Insert Interval

164. Maximum Gap

給一個未排序數組,返回它在排好序的時候,連續兩個元素之間的最大差值。
這個問題用到了桶排序,核心要點是最大gap的下界是(maxV - minV )/ (sSize - 1)。依照這個思路簡化我們需要計算的部分,從而時間複雜度是O(2N+K),K是桶的數目,空間複雜度是O(3K)。滿足時空複雜度爲線性的要求。
Maximum Gap

488. Zuma Game

回溯+剪枝的應用。
Zuma Game

440. K-th Smallest in Lexicographical Order

構建一個十叉樹,很巧妙
K-th Smallest in Lexicographical Order

28. Implement strstr

KMP算法的一個學習。
strstr

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章