# Leetcode刷題學習筆記 -- Stack ### Note 1. 使用 st.top()或是st.pop() 之前==必須先判斷stack是否為empty()。== 2. monotone stack: stack中保持一定的大小順序。 ### 使用vector/string來模擬stack 我們可以在vector/string中使用two pointer來模擬stack,這樣的好處是可以減少很多不必要的push/pop。 [1047. Remove All Adjacent Duplicates In String](https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/description/) ```cpp= // 把i當成是stack的top,這樣的話0就會表示有東西, // 所以i == -1才會表示沒stack empty。 string s{"abbaca"}; int i = -1; // stack is empty for(int j = 0; j < sz; ++j) { // 當stack不是empty,且stack top == s[j] // 則 stack pop(--i) if(i != -1 && s[i] == s[j]) --i; else s[++i] = s[j]; // stack push } return i == -1 ? "" : s.substr(0, i + 1); ``` #### stack initialization ```cpp int i = -1; ``` #### check if stack is empty ```cpp boolean isEmpty() { return i == -1; } ``` #### stack push ```cpp s[++i] = s[j]; // 因為i指在top,所以必須先++i ``` ### stack pop ```cpp --i; // 直接把index - 1,當empty的時候會變成-1。 ``` ### [155. Min Stack(Easy)](https://leetcode.com/problems/min-stack/) 實現一個MinStack,除了一般stack的功能push(), pop()和top()之外,還可以取得stack中的最小值getMin()。 > 1. 這邊使用兩個stack,一個正常使用s1,一個是monotonic stack(遞減) s2,來記錄最小值。 > 2. push的時候,因為s2為monotonic所以只推比top還小的值。 > 3. pop的時候,如果s1和s2的top一樣,則兩個一起pop。 > 4. 因為s2有著和s1一樣的順續,只是他只把比自己小的推進去,因為是min stack。 ```cpp= class MinStack { stack<int> s1, s2; public: MinStack() {} void push(int val) { if(s2.empty() || val <= s2.top()) s2.push(val); s1.push(val); } void pop() { if(s1.top() == s2.top()) s2.pop(); s1.pop(); } int top() {return s1.top();} int getMin() {return s2.top();} }; ``` ### [316. Remove Duplicate Letters](https://leetcode.com/problems/remove-duplicate-letters/) 刪除重複出現的字元,每個字元只能出現一次,並且照字典排序。 ```c string removeDuplicateLetters(string s) { // string 可以使為stack操作 int m[256] = {0}, visited[256] = {0}; // 使用256避免char<->int轉換,減少失誤 string res = "0"; for (auto a : s) ++m[a]; for (auto a : s) { --m[a]; // 後面還剩多少個 if(visited[a]) continue; // 已經在裡面了就繼續,因為題目說只能出現一次 while(a < res.back() && m[res.back()]) { // 目前的char比最後一個還小,而且back()在後面還有 visited[res.back()] = 0; res.pop_back(); } res.push_back(a); visited[a] = 1; } return res.substr(1); } ``` ### [1209. Remove All Adjacent Duplicates in String II](https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string-ii/description/) 這題為[1047. Remove All Adjacent Duplicates In String](https://leetcode.com/problems/remove-all-adjacent-duplicates-in-string/description/)的延伸題,原本是兩個一樣就可以刪除,現在是K個一樣才可以刪除。原本的題目是K=2。 > 1. 可以使用stack<pair<char, int>>多一個欄位來儲存char的次數。 > 2. 因為是stack也可以使用two pointers來模擬stack。 > 3. method1和method2都使用額外的空間紀錄count,所以返回的答案也必須要根據count重建。 ```cpp string removeDuplicates(string s, int k) { // method 1 : stack stack<pair<char, int>> st; for(auto& c :s) { if(!st.empty() && st.top().first == c) { if(st.top().second == k - 1) st.pop(); else st.top().second++; } else st.push(make_pair(c, 1)); } string rtn{""}; while(!st.empty()) { rtn = string(st.top().second, st.top().first) + rtn; st.pop(); } return rtn; } ``` ```cpp string removeDuplicates(string s, int k) { // method 2 : two pointer int sz = s.size(); int i = -1; vector<int> cnt(sz); for(int j = 0; j < sz; ++j) { if(~i && s[i] == s[j]) { if(cnt[i] == k - 1) --i; else cnt[i]++; } else { s[++i] = s[j]; cnt[i] = 1; } } if(i == -1) return ""; else { string rtn{""}; for(int j = 0; j <= i; ++j) rtn += string(cnt[j], s[j]); return rtn; } } ``` ### [895. Maximum Frequency Stack](https://leetcode.com/problems/maximum-frequency-stack/description/) 設計一個stack,pop的時候是把最大freq的element丟出來。 > 1. 一開始使用兩個unordered_map,一個統計數量,一個統計每個freq的element。這樣做每次push或是pop都在搬移element出現在freq的位置。 > 2. 參考答案,使用unordered_map<int, stack<int>>。不同的頻率有不同的stack。因為不同頻率的n,可以在stack中被排列。 > 3. 一個stack可以被拆成3個stack,如下圖 ``` ex: [5, 7, 5, 7, 4, 5] freq1-stack | | | freq2-stack | | freq3-stack | <-- maxfreq ``` ```cpp class FreqStack { unordered_map<int, int> freq; //value, count unordered_map<int, stack<int>> m; //freq, stack<value> int maxfreq{0}; // 因為一個數(n)可以表示為, // freq1-n, freq2-n, freq3-n, ... 每個出現頻率的n // 所以使用unordered_map<int, stack<int>> m; 來表示每個頻率的stack public: FreqStack() { } void push(int val) { freq[val]++; m[freq[val]].push(val); maxfreq = max(maxfreq, freq[val]); } int pop() { int rtn = m[maxfreq].top(); m[maxfreq].pop(); freq[rtn]--; if(m[maxfreq].size() == 0) maxfreq--; return rtn; } }; ``` ###### tags: `leetcode` `刷題`