11.1 C++ STL
C++ 提供的數(shù)據(jù)結(jié)構(gòu)包括:
-
Sequence Containers:維持順序的容器。
- vector:動(dòng)態(tài)數(shù)組,用于 O(1) 的隨機(jī)讀取。因?yàn)榇蟛糠炙惴ǖ臅r(shí)間復(fù)雜度都會(huì)大于 O(n) ,因此我們經(jīng)常新建 vector 來(lái)存儲(chǔ)各種數(shù)據(jù)或中間變量。
- list:雙向鏈表,也可以當(dāng)作 stack 和 queue 來(lái)使用。由于 LeetCode 的題目多用 Node 來(lái)表示鏈表,且鏈表不支持快速隨機(jī)讀取,因此很少用到該數(shù)據(jù)結(jié)構(gòu)。 一個(gè)例外是經(jīng)典的 LRU 問(wèn)題,需要利用鏈表的特性來(lái)解決。
- deque:雙端隊(duì)列,既支持 O(1) 的隨機(jī)讀取,又支持 O(1) 時(shí)間的頭部增刪和尾部增刪,不過(guò)有一定的額外開(kāi)銷。
- array:固定大小的數(shù)組,一般不使用。
- forward_list:單向鏈表,一般不使用。
-
Container Adaptors:基于其他容器實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)。
- stack:后入先出(LIFO) 的數(shù)據(jù)結(jié)構(gòu),默認(rèn)基于 deque 實(shí)現(xiàn),stack常用于深度優(yōu)先搜索、字符串匹配問(wèn)題以及單調(diào)棧問(wèn)題。
- queue:先入先出(FIFO) 的數(shù)據(jù)結(jié)構(gòu),默認(rèn)基于 deque 實(shí)現(xiàn),queue 常用于廣度優(yōu)先搜索。
- priority_queue:最大值先出的數(shù)據(jù)結(jié)構(gòu),默認(rèn)基于 vector 是實(shí)現(xiàn)堆結(jié)構(gòu)。它可以在 O(n logn) 的時(shí)間排序數(shù)組, O(logn) 的時(shí)間插入任意值,O(1) 的時(shí)間獲得最大值, O(logn) 的時(shí)間刪除最大值。 priority_queue 常用于維護(hù)數(shù)據(jù)結(jié)構(gòu)并快速獲取最大或最小值。
-
Associative Containers:實(shí)現(xiàn)了排好序的數(shù)據(jù)結(jié)構(gòu)。
-
set:有序集合,元素不可以重復(fù),底層實(shí)現(xiàn)默認(rèn)為紅黑樹(shù),即一種特殊的二叉查找樹(shù)(BST)。它可以在 O(nlogn) 的時(shí)間排序數(shù)組,O(logn) 的時(shí)間插入、刪除、查找任意值,O(logn) 的時(shí)間獲得最小或最大值。
這里注意,set 和 priority_queue 都可以用于維護(hù)數(shù)據(jù)結(jié)構(gòu)并快速獲取最大最小值,但是它們的時(shí)間復(fù)雜度和功能略有區(qū)別。比如, priority_queue 默認(rèn)不支持刪除任意值,而 set 獲得最大或最小值的時(shí)間復(fù)雜度略高。
-
multiset:支持重復(fù)元素的 set。
-
map: 有序映射或有序表,在 set 的基礎(chǔ)上加上映射關(guān)系,可以對(duì)每個(gè)元素 key 存一個(gè)值 value。
-
multimap:支持重復(fù)元素的 map。
-
-
Unordered Associative Containers:對(duì)每個(gè) Associative Containers 實(shí)現(xiàn)了哈希版本。
- unordered_set :哈希集合,可以在 O(1) 的時(shí)間快速插入、查找、刪除元素,常用于快速查詢一個(gè)元素是否在這個(gè)容器內(nèi)。
- unordered_multiset:支持重復(fù)元素的 unordered_set 。
- unordered_map:哈希映射或哈希表,在 unordered_set 的基礎(chǔ)上加上映射關(guān)系,可以對(duì)每一個(gè)元素 key 存一個(gè)值 value。在某些情況下,如果 key 的范圍已知且較小,我們也可以用 vector 代替 unordered_map,用位置表示 key,每個(gè)位置的值表示 value。
- unordered_multimap:支持重復(fù)元素的 unordered_map。
11.2 數(shù)組
448. 找到所有數(shù)組中消失的數(shù)字(簡(jiǎn)單)
思路及代碼: 448. 找到所有數(shù)組中消失的數(shù)字
48. 旋轉(zhuǎn)圖像(中等)
思路及代碼: 48. 旋轉(zhuǎn)圖像
74. 搜索二維矩陣(中等)
思路及代碼: 74. 搜索二維矩陣
240. 搜索二維矩陣 II(中等)
思路及代碼:240. 搜索二維矩陣 II
769. 最多能完成排序的塊(中等)
思路及代碼: 769. 最多能完成排序的塊
768. 最多能完成排序的塊 II(困難)
思路及代碼: 768. 最多能完成排序的塊 II
11.3 棧和隊(duì)列
232. 用棧實(shí)現(xiàn)隊(duì)列(簡(jiǎn)單)
思路及代碼: 232. 用棧實(shí)現(xiàn)隊(duì)列
155. 最小棧(中等)
思路及代碼: 155. 最小棧
20. 有效的括號(hào)(簡(jiǎn)單)
思路及代碼: 20. 有效的括號(hào)
11.4 單調(diào)棧
單調(diào)棧 通過(guò)維持棧內(nèi)值的單調(diào)遞增(遞減)性,在整體 O(n) 的時(shí)間內(nèi)處理需要大小比較的問(wèn)題。
739. 每日溫度(中等)
思路及代碼: 739. 每日溫度
11.5 優(yōu)先隊(duì)列
-
優(yōu)先隊(duì)列可以在 O(1) 時(shí)間內(nèi)獲得最大值,并且可以在 O(log n) 時(shí)間內(nèi)取出最大值或插入任意值。
-
優(yōu)先隊(duì)列常常用 堆 來(lái)實(shí)現(xiàn)。堆是一個(gè)完全二叉樹(shù),其每個(gè)節(jié)點(diǎn)的值總是大于等于子節(jié)點(diǎn)的值。實(shí)際實(shí)現(xiàn)堆的時(shí)候,通常用數(shù)組而不是指針建立一個(gè)樹(shù),這是因?yàn)槎咽峭耆鏄?shù),所以用數(shù)組表示的時(shí)候,位置 i 的節(jié)點(diǎn)的父節(jié)點(diǎn)位置一定是
(i-1)/2
,而它的兩個(gè)子節(jié)點(diǎn)的位置又一定分別為2i+1
和2i+2
。 -
以下是堆的實(shí)現(xiàn)方法,其中最核心的兩個(gè)操作是上浮和下沉:.
-
如果一個(gè)節(jié)點(diǎn)比父節(jié)點(diǎn)大,那么需要交換這兩個(gè)節(jié)點(diǎn);交換后它可能比新的父節(jié)點(diǎn)還大,因此需要不斷進(jìn)行比較和交換操作,稱之為上浮;
-
如果一個(gè)節(jié)點(diǎn)比父節(jié)點(diǎn)小,那么也需要不斷地進(jìn)行向下比較和交換操作,稱之為下沉。
如果一個(gè)節(jié)點(diǎn)有兩個(gè)子節(jié)點(diǎn),我們總是交換最大的子節(jié)點(diǎn)。
-
vector<int> heap;
// 上浮
void swim(int pos){
while(pos > 0 && heap[(pos-1)/2] < heap[pos]){
swap(heap[(pos-1)/2], heap[pos]);
pos = (pos - 1) / 2;
}
}
// 下沉
void sink(int pos){
while(2 * pos + 1 <= N){
int i = 2 * pos + 1;
// 兩個(gè)子節(jié)點(diǎn)進(jìn)行比較,找到更大的子節(jié)點(diǎn)
if(i < N && heap[i] < heap[i+1]) ++i;
if(heap[pos] >= heap[i]) break;
swap(heap[pos], heap[i]);
pos = i;
}
}
// 插入任意值:把新數(shù)字放到最后一位,然后上浮
void push(int k){
heap.push_back(k);
swim(heap.size()-1);
}
// 刪除最大值:把最后一個(gè)數(shù)字挪到開(kāi)頭,然后下沉
void pop(){
// 原本的heap[0]就是最大值
heap[0] = heap.back();
heap.pop_back();
sink(0);
}
// 獲取最大值
int top(){
return heap[0];
}
- 通過(guò)將算法中的大于號(hào)和小于號(hào)互換,我們也可以得到一個(gè)快速獲得最小值的優(yōu)先隊(duì)列。
- 另外,如果在維持大小關(guān)系的同時(shí),還需要支持查找任意值、刪除任意值、維護(hù)所有數(shù)字的大小關(guān)系等操作,可以考慮使用 set 或 map來(lái)代替優(yōu)先隊(duì)列。
23. 合并 K 個(gè)升序鏈表(困難)
思路及代碼: 23. 合并 K 個(gè)升序鏈表
218. 天際線問(wèn)題(困難)
思路及代碼: 218. 天際線問(wèn)題
11.6 雙端隊(duì)列
239. 滑動(dòng)窗口最大值(困難)
思路及代碼: 239. 滑動(dòng)窗口最大值
11.7 哈希表
- 哈希表 ,又稱散列表,使用 O(n) 空間復(fù)雜度存儲(chǔ)數(shù)據(jù),通過(guò)哈希函數(shù)映射位置,從而實(shí)現(xiàn)近似 O(1) 時(shí)間復(fù)雜度的插入、查找和刪除操作。
- c++ 中的哈希集為 unordered_set ,可以查找元素是否在集合中,如果需要同時(shí)存儲(chǔ)鍵和值,則需要用 unordered_map,可以用來(lái)統(tǒng)計(jì)頻率,記錄內(nèi)容等。如果元素有限個(gè),并且范圍不大,則可以用一個(gè)固定大小的數(shù)組來(lái)存儲(chǔ)或統(tǒng)計(jì)元素。例如我們需要統(tǒng)計(jì)一個(gè)字符串中所有字母的出現(xiàn)次數(shù),則可以用一個(gè)長(zhǎng)度為 26 的數(shù)組來(lái)進(jìn)行統(tǒng)計(jì),其哈希函數(shù)即為字母在字母表的位置,這樣空間復(fù)雜度就可以降為常數(shù)。
1. 兩數(shù)之和(簡(jiǎn)單)
思路及代碼: 1. 兩數(shù)之和
128. 最長(zhǎng)連續(xù)序列(中等)
思路及代碼: 128. 最長(zhǎng)連續(xù)序列
149. 直線上最多的點(diǎn)數(shù)(困難)
思路及代碼: 149. 直線上最多的點(diǎn)數(shù)
11.8 多重集合和映射
332. 重新安排行程(困難)
思路及代碼: 332. 重新安排行程
11.9 前綴和與積分圖
- 一維的前綴和,二維的積分圖,都是把每個(gè)位置之前的一維線段或二維矩形預(yù)先存儲(chǔ),方便加速計(jì)算。如果需要對(duì)前綴和或積分圖的值做尋址,則要存在哈希表里;如果要對(duì)每個(gè)位置記錄前綴和或積分圖的值,則可以存儲(chǔ)到一維或二維數(shù)組里,常常伴隨著動(dòng)態(tài)規(guī)劃。
303. 區(qū)域和檢索 - 數(shù)組不可變(簡(jiǎn)單)
思路與代碼: 303. 區(qū)域和檢索 - 數(shù)組不可變
304. 二維區(qū)域和檢索 - 矩陣不可變(中等)
思路及代碼: 304. 二維區(qū)域和檢索 - 矩陣不可變
560. 和為 K 的子數(shù)組(中等)
思路及代碼: 560. 和為 K 的子數(shù)組
11.10 練習(xí)
566. 重塑矩陣(簡(jiǎn)單)
思路及代碼: 566. 重塑矩陣
225. 用隊(duì)列實(shí)現(xiàn)棧(簡(jiǎn)單)
思路及代碼: 225. 用隊(duì)列實(shí)現(xiàn)棧
503. 下一個(gè)更大元素 II(中等)
思路及代碼: 503. 下一個(gè)更大元素 II
217. 存在重復(fù)元素(簡(jiǎn)單)
思路及代碼: 217. 存在重復(fù)元素
697. 數(shù)組的度(簡(jiǎn)單)
思路及代碼: 697. 數(shù)組的度
594. 最長(zhǎng)和諧子序列(簡(jiǎn)單)
思路及代碼: 594. 最長(zhǎng)和諧子序列
287 . 尋找重復(fù)數(shù)(中等)
思路及代碼: 287. 尋找重復(fù)數(shù)
313. 超級(jí)丑數(shù)
思路及代碼: 313. 超級(jí)丑數(shù)
870 . 優(yōu)勢(shì)洗牌
思路及代碼: 870 . 優(yōu)勢(shì)洗牌
307 . 區(qū)域和檢索 - 數(shù)組可修改
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-649027.html
思路及代碼: 307 . 區(qū)域和檢索 - 數(shù)組可修改文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-649027.html
到了這里,關(guān)于【LeetCode】《LeetCode 101》第十一章:妙用數(shù)據(jù)結(jié)構(gòu)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!