LeetCode题解-03(栈、队列、双指针、哈希表)

目录

LeetCode题解

chap-7: 栈、队列#

1、最小栈【设计】#

Copy
class MinStack { public: stack<int> a,b; /** initialize your data structure here. */ MinStack() { } void push(int val) { a.push(val); if(b.empty() || val <= b.top()) b.push(val); } void pop() { auto t = a.top(); if(b.size() && b.top() == t) b.pop(); a.pop(); } int top() { return a.top(); } int getMin() { return b.top(); } };

2、比较含退格的字符串#

Copy
class Solution { public: bool backspaceCompare(string s, string t) { stack<char>a,b; for(auto c:s){ if(c == '#'){ if(a.empty()) continue; else a.pop(); }else a.push(c); } for(auto c:t){ if(c == '#'){ if(b.empty()) continue; else b.pop(); }else b.push(c); } if(a.size() != b.size()) return false; while(a.size()){ if(a.top() != b.top()) return false; a.pop(), b.pop(); } return true; } }; // 进一步地 class Solution { public: string get(string& s) { string res; for (auto c: s) if (c == '#') { if (res.size()) res.pop_back(); } else { res += c; } return res; } bool backspaceCompare(string s, string t) { return get(s) == get(t); } };

3、设计一个支持增量操作的栈 【×】#

Copy
// inc部分O(k)-O(1) class CustomStack { public: vecto1r<int> inc_arr; stack<int> st; int m_size,cnt = 0; CustomStack(int maxSize) { m_size = maxSize; inc_arr.resize(maxSize + 1,0); } void push(int x) { if(cnt < m_size){ cnt ++; st.push(x); } } int pop() { if(cnt == 0) return -1; int p = st.top(); st.pop(); if(inc_arr[cnt] != 0){ inc_arr[cnt - 1] += inc_arr[cnt]; p += inc_arr[cnt]; inc_arr[cnt] = 0; } cnt --; return p; } void increment(int k, int val) { inc_arr[min(k,cnt)] += val; } };

4、设计循环队列#

Copy
class MyCircularQueue { public: int hh = 0, tt = 0; vector<int> q; /** Initialize your data structure here. Set the size of the queue to be k. */ MyCircularQueue(int k) { q.resize(k + 1); } /** Insert an element into the circular queue. Return true if the operation is successful. */ bool enQueue(int value) { if (isFull()) return false; q[tt ++ ] = value; if (tt == q.size()) tt = 0; return true; } /** Delete an element from the circular queue. Return true if the operation is successful. */ bool deQueue() { if (isEmpty()) return false; hh ++ ; if (hh == q.size()) hh = 0; return true; } /** Get the front item from the queue. */ int Front() { if (isEmpty()) return -1; return q[hh]; } /** Get the last item from the queue. */ int Rear() { if (isEmpty()) return -1; int t = tt - 1; if (t < 0) t += q.size(); return q[t]; } /** Checks whether the circular queue is empty or not. */ bool isEmpty() { return hh == tt; } /** Checks whether the circular queue is full or not. */ bool isFull() { return (tt + 1) % q.size() == hh; } };

5、设计循环双端队列#

Copy
class MyCircularDeque { public: int hh = 0, tt = 0; vector<int> q; /** Initialize your data structure here. Set the size of the deque to be k. */ MyCircularDeque(int k) { q.resize(k + 1); } int get(int x) { return (x + q.size()) % q.size(); } /** Adds an item at the front of Deque. Return true if the operation is successful. */ bool insertFront(int value) { if (isFull()) return false; hh = get(hh - 1); q[hh] = value; return true; } /** Adds an item at the rear of Deque. Return true if the operation is successful. */ bool insertLast(int value) { if (isFull()) return false; q[tt ++ ] = value; tt = get(tt); return true; } /** Deletes an item from the front of Deque. Return true if the operation is successful. */ bool deleteFront() { if (isEmpty()) return false; hh = get(hh + 1); return true; } /** Deletes an item from the rear of Deque. Return true if the operation is successful. */ bool deleteLast() { if (isEmpty()) return false; tt = get(tt - 1); return true; } /** Get the front item from the deque. */ int getFront() { if (isEmpty()) return -1; return q[hh]; } /** Get the last item from the deque. */ int getRear() { if (isEmpty()) return -1; return q[get(tt - 1)]; } /** Checks whether the circular deque is empty or not. */ bool isEmpty() { return hh == tt; } /** Checks whether the circular deque is full or not. */ bool isFull() { return get(hh - 1) == tt; } };

6、验证栈序列#

Copy
class Solution { public: bool validateStackSequences(vector<int>& pushed, vector<int>& popped) { stack<int> s; int j = 0; for(int i = 0;i<pushed.size();i++){ if(popped[j] == pushed[i]) { j++; while(s.size() && s.top() == popped[j]){s.pop(); j++;} } else s.push(pushed[i]); } while(s.size()){ auto t = s.top(); s.pop(); if(t != popped[j]) return false; else j++; } return true; } };

7、删除字符串中的所有相邻重复项#

Copy
class Solution { public: string removeDuplicates(string s) { string stk; for(auto &c:s){ if(stk.size() && stk.back() == c) stk.pop_back(); else stk.push_back(c); } return stk; } };

8、删除字符串中的所有相邻重复项 II#

Copy
class Solution { public: string removeDuplicates(string s, int k) { string stk("#"); stack<int> cnt; cnt.push(1); for(int i = 0 ; i < s.size() ; i++) { if(s[i] == stk.back()) cnt.push(cnt.top()+1); else cnt.push(1); stk += s[i]; if(cnt.top() >= k) { for(int j = 0 ; j < k ; j++) { stk.pop_back(); cnt.pop(); } } } return stk.substr(1); } };

[Go Back~~](# LeetCode题解)

section7-1: 栈、队列重构#

1、用队列实现栈#

Copy
class MyStack { public: /** Initialize your data structure here. */ queue<int> a,b; MyStack() { } /** Push element x onto stack. */ void push(int x) { a.push(x); } /** Removes the element on top of the stack and returns that element. */ int pop() { while(a.size() > 1) b.push(a.front()), a.pop(); int t = a.front(); a.pop(); while(b.size()) a.push(b.front()), b.pop(); return t; } /** Get the top element. */ int top() { while(a.size() > 1) b.push(a.front()), a.pop(); int t = a.front(); b.push(a.front()), a.pop(); while(b.size()) a.push(b.front()), b.pop(); return t; } /** Returns whether the stack is empty. */ bool empty() { return a.empty(); } };

2、用栈实现队列#

Copy
class MyQueue { public: /** Initialize your data structure here. */ stack<int> a,b; MyQueue() { } void in2out(){ while(a.size()) b.push(a.top()), a.pop(); } /** Push element x to the back of queue. */ void push(int x) { a.push(x); } /** Removes the element from in front of queue and returns that element. */ int pop() { if(b.empty()) in2out(); int t = b.top(); b.pop(); return t; } /** Get the front element. */ int peek() { if(b.empty()) in2out(); return b.top(); } /** Returns whether the queue is empty. */ bool empty() { return a.empty() && b.empty(); } };

section7-2: 单调栈#

1、接雨水#

Copy
class Solution { public: int trap(vector<int>& h) { stack<int> help; int ans = 0; for(int i=0;i<h.size();i++){ if(help.empty()) help.push(i); else{ if(h[i] < h[help.top()]) help.push(i); else{ // h > top() auto t = help.top(); help.pop(); while(help.size() && h[t] <= h[i]){ auto q = help.top(); if(h[q] <= h[i]) help.pop(); ans += (min(h[q],h[i]) - h[t])*(i-q-1); t = q; } help.push(i); } } } return ans; } }; // 逻辑优化 class Solution { public: int trap(vector<int>& h) { stack<int> help; int ans = 0; for(int i=0;i<h.size();i++){ while(!help.empty() && h[help.top()] <= h[i]){ auto t = help.top(); help.pop(); if(help.empty()) break; ans += (min(h[help.top()],h[i])-h[t])*(i-help.top()-1); } help.push(i); } return ans; } };

2、柱状图中最大的矩形#

Copy
class Solution { public: int largestRectangleArea(vector<int>& h) { int ans = 0; h.push_back(-1); stack<int> s; for(int i=0;i<h.size();i++){ while(s.size() && h[i] < h[s.top()]){ auto t = s.top(); s.pop(); if(s.empty()) ans = max(ans,h[t] * i); else ans = max(ans,h[t]*(i-s.top()-1)); } s.push(i); } return ans; } };

3、最大矩形#

Copy
class Solution { public: int maximalRectangle(vector<vector<char>>& matrix) { if(matrix.size() <= 0) return 0; int ans = 0, m = matrix.size(), n = matrix[0].size(); vector<int>help = vector<int>(n+1,0); for(int i=0;i<m;i++){ for(int j=0;j<n;j++) if(matrix[i][j] == '1') help[j]+=1; else help[j] = 0; stack<int> s; for(int j=0;j<=n;j++){ while(s.size() && help[j] < help[s.top()]){ auto t = s.top(); s.pop(); if(s.empty()) ans = max(ans,help[t]*j); else ans = max(ans,help[t]*(j-s.top()-1)); } s.push(j); } } return ans; } };

4、下一个更大元素 I#

Copy
class Solution { public: vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) { unordered_map<int,int>hash; stack<int> s; for(int i=nums2.size()-1;~i;i--){ if(s.empty()) hash[nums2[i]] = -1, s.push(nums2[i]); else{ while(s.size() && nums2[i] > s.top()){ s.pop(); if(s.empty()) { hash[nums2[i]] = -1, s.push(nums2[i]); break; } } if(nums2[i] < s.top()) hash[nums2[i]] = s.top(), s.push(nums2[i]); } } vector<int> ans; for(auto &num:nums1) ans.push_back(hash[num]); return ans; } };

5、下一个更大元素 II【破环成链】#

Copy
class Solution { public: vector<int> nextGreaterElements(vector<int>& nums) { int n = nums.size(); vector<int> ans(n,0); nums.insert(nums.end(),nums.begin(),nums.end()); stack<int> s; for(int i = 2*n-1;~i;i--){ int x = nums[i]; while(s.size() && x >= s.top()) s.pop(); if(i<n){ if(s.empty()) ans[i] = -1; else ans[i] = s.top(); } s.push(x); } return ans; } };

6、每日温度#

Copy
class Solution { public: vector<int> dailyTemperatures(vector<int>& t) { stack<int> s; int n = t.size(); vector<int> ans(n); for(int i=n-1;~i;i--){ while(s.size() && t[i] >= t[s.top()]) s.pop(); if(s.empty()){ ans[i] = 0; }else ans[i] = s.top()-i; s.push(i); } return ans; } };

[Go Back~~](# LeetCode题解)

section7-3: 单调队列#

1、滑动窗口最大值#

Copy
class Solution { public: vector<int> maxSlidingWindow(vector<int>& nums, int k) { deque<int> q; vector<int> ans; for(int i = 0;i<nums.size();i++){ if (q.size() && i - k + 1 > q.front()) q.pop_front(); while(q.size() && nums[q.back()] <= nums[i]) q.pop_back(); q.push_back(i); if(i>=k-1) ans.push_back(nums[q.front()]); } return ans; } };

section7-4:逆波兰表达式/计算器#

1、逆波兰表达式求值#

Copy
class Solution { public: int evalRPN(vector<string>& tokens) { stack<int> s; for(auto &t:tokens){ if(t == "+" || t == "-" || t == "*" || t == "/"){ int a = s.top(); s.pop(); int b = s.top(); s.pop(); if(t == "+") s.push(b+a); if(t == "-") s.push(b-a); if(t == "*") s.push(b*a); if(t == "/") s.push(b/a); }else{ s.push(stoi(t)); } } return s.top(); } };

2、基本计算器【×】#

Copy
class Solution { public: void eval(stack<int>& num,stack<char>& op) { auto b=num.top();num.pop(); auto a=num.top();num.pop(); auto c=op.top();op.pop(); if(c=='+') num.push(a+b); else num.push(a-b); } int calculate(string rs) { string s; for(auto c:rs) if(c!=' ') s+=c; stack<int> num; stack<char> op; for(int i=0;i<s.size();i++) { auto c=s[i]; if(isdigit(c)) { int x=0,j=i; while(j<s.size() && isdigit(s[j])) x=x*10+(s[j++]-'0'); i=j-1; num.push(x); } else if(c=='(') op.push(c); else if(c==')') { while(op.top()!='(') eval(num,op); op.pop(); } else { if(!i || s[i-1]=='(' || s[i-1]=='+' || s[i-1]=='-') num.push(0); while(op.size() && op.top()!='(') eval(num,op); op.push(c); } } while(op.size()) eval(num,op); return num.top(); } };

3、基本计算器 II#

Copy
class Solution { public: int calculate(string s) { char pre = '+'; vector<int> help; for(int i = 0;i<s.size();i++){ if(s[i] == ' ') continue; if(isdigit(s[i])){ int j = i; while(j<s.size() && isdigit(s[j])) j++; int t = stoi(s.substr(i,j-i)); i = j-1; switch (pre){` case '+':help.push_back(t); break; case '-':help.push_back(-t); break; case '*':help.back() = (help.back() * t); break; default:help.back() = (help.back()/t); } }else{ pre = s[i]; } } return accumulate(help.begin(),help.end(),0); } };

section7-5:括号序列#

1、有效的括号#

Copy
class Solution { public: bool isValid(string s) { stack<char> stk; for(auto c:s){ if(c == '(' || c == '[' || c == '{') stk.push(c); else{ if(stk.size()){ auto t = stk.top(); if(c-t==')'-'(' || c-t==']'-'[' || c-t=='}'-'{') stk.pop(); else return false; } else return false; } } return stk.empty(); } };

2、最长有效括号#

Copy
class Solution { public: int longestValidParentheses(string s) { stack<int> stk; // 记录左括号位置 int start = 0, ans = 0; for(int i = 0;i<s.size();i++){ if(s[i] == '(') stk.push(i); else{ if(stk.empty()) start = i+1; else{ stk.pop(); if(stk.empty()) ans = max(i-start+1,ans); else ans = max(i-stk.top(),ans); } } } return ans; } };

[Go Back~~](# LeetCode题解)

chap-8:双指针#

section8.1 同向双指针#

1、外观数列【模拟】#

Copy
class Solution { public: string countAndSay(int n) { string ans = "1"; while(--n){ string temp; for(int i = 0;i<ans.size();i++){ int j = i+1,cnt=1; while(j<ans.size() && ans[j] == ans[i]) cnt++,j++; temp += to_string(cnt) + ans[i]; i = j-1; } ans = temp; } return ans; } };

2、最后一个单词的长度#

Copy
class Solution { public: int lengthOfLastWord(string s) { int n = s.length() - 1; while(n >=0 && s[n] == ' ') n--; int i = n; while(~i && s[i] != ' ') i--; return i>=0 ? n-i:n+1; } };

3、删除有序数组中的重复项#

Copy
class Solution { public: int removeDuplicates(vector<int>& nums) { if(nums.empty()) return 0; int j=0; for(int i=j+1;i<nums.size();i++){ if(nums[j] == nums[i])continue; else nums[++j] = nums[i]; } return j+1; } };

4、删除有序数组中的重复项 II#

Copy
class Solution { public: int removeDuplicates(vector<int>& nums) { if(nums.empty()) return 0; int j=0; for(int i = j+1;i<nums.size();i++){ if(nums[j] == nums[i]){ if(j && nums[j-1] == nums[j]) continue; else nums[++j] = nums[i]; }else nums[++j] = nums[i]; } return j+1; } };

5、移除元素#

Copy
class Solution { public: int removeElement(vector<int>& nums, int val) { if(nums.empty()) return 0; int len = 0; for(int i=len;i<nums.size();i++){ if(nums[i] == val) continue; else { nums[len++] = nums[i]; } } return len; } };

6、颜色分类#

Copy
class Solution { public: void sortColors(vector<int>& nums) { int l=-1,r=nums.size(); for(int i=0;i<r;){ if(nums[i] == 0){ swap(nums[++l],nums[i]); i = l+1; }else if(nums[i] == 2){ swap(nums[--r],nums[i]); }else i++; } } };

7、合并两个有序数组#

Copy
class Solution { public: void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { int i = m-1, j = n-1, k = m+n-1; while(~i && ~j){ if(nums1[i] > nums2[j]) nums1[k--] = nums1[i--]; else nums1[k--] = nums2[j--]; } while(~i) nums1[k--] = nums1[i--]; while(~j) nums1[k--] = nums2[j--]; } };

8、移动零#

Copy
class Solution { public: void moveZeroes(vector<int>& nums) { int i = 0; while(i<nums.size() && nums[i])i++; for(int j = i+1;j<nums.size();j++){ if(nums[j] == 0)continue; else swap(nums[i++],nums[j]); } } };

9、判断子序列#

Copy
class Solution { // 双指针 public: bool isSubsequence(string t, string s) { int i = 0, j = 0; while(i<s.size() && j<t.size()){ if(s[i] == t[j]) i++,j++; else i++; } return j==t.size(); } }; // 进阶问题处理思路 class Solution { public: bool isSubsequence(string s, string t) { int n = s.size(), m = t.size(); vector<vector<int>> f(m+1, vector<int>(26,0)); for(int i = 0;i<26;i++) f[m][i] = m; for(int i = m-1;i>=0;i--){ for(int j = 0;j<26;j++){ if(j == t[i]-'a') f[i][j] = i; else f[i][j] = f[i+1][j]; } } int idx = 0; // f起始处开始搜 for (int i = 0; i < n; i++) { if (f[idx][s[i] - 'a'] == m) { return false; } idx = f[idx][s[i] - 'a'] + 1; // 下一个位置 } return true; } };

10、字符串中的单词数#

Copy
// 库函数 class Solution { public: int countSegments(string s) { stringstream sin(s); int ans = 0; string c; while(sin>>c) ans++; return ans; } }; // 双指针 class Solution { public: int countSegments(string s) { int res = 0; for(int i = 0;i<s.size();i++){ if(s[i] == ' ')continue; int j = i+1; while(j<s.size() && s[j] != ' ')j++; res++; i = j-1; } return res; } };

11、压缩字符串#

Copy
class Solution { public: int compress(vector<char>& chars) { int ans = 0; for(int i = 0;i<chars.size();i++){ int j = i+1, t = 1; while(j<chars.size() && chars[j] == chars[i]) j++, t++; chars[ans++] = chars[i]; if(t > 1) { i = j-1; string s = to_string(t); for(j=0;j<s.size();j++) chars[ans++] = s[j]; } } return ans; } };

12、最大连续 1 的个数#

Copy
class Solution { public: int findMaxConsecutiveOnes(vector<int>& nums) { int ans = 0; for(int i=0;i<nums.size();i++){ if(nums[i] == 0)continue; else{ int j = i+1; while(j<nums.size() && nums[j] == 1) j++; ans = max(ans,j-i); i = j-1; } } return ans; } };

13、划分字母区间[×]#

Copy
class Solution { public: vector<int> partitionLabels(string s) { unordered_map<int,int> hash; int i = 0,start = 0,end = 0; vector<int> ans; for(;i<s.size();i++)hash[s[i]] = i; for(i = 0;i<s.size();i++){ end = max(end,hash[s[i]]); if(i == end){ ans.push_back(end - start + 1); start = end = i+1; } } return ans; } };

14、按奇偶排序数组 II#

Copy
class Solution { public: vector<int> sortArrayByParityII(vector<int>& nums) { int slow = 0, fast = slow+1; while(true){ while(slow < nums.size() && nums[slow]%2 == 0) slow+=2; while(fast < nums.size() && nums[fast]%2) fast+=2; if(fast >= nums.size()) break; else{ swap(nums[slow],nums[fast]); } } return nums; } };

15、区间列表的交集#

Copy
class Solution { public: vector<vector<int>> intervalIntersection(vector<vector<int>>& f, vector<vector<int>>& s) { vector<vector<int>> ans; for(int i = 0,j = 0;i<f.size() && j<s.size();){ if(f[i][0] <= s[j][1] && f[i][1] >= s[j][0]) ans.push_back({max(f[i][0],s[j][0]),min(f[i][1],s[j][1])}); if(f[i][1] <= s[j][1]) i++; else j++; } return ans; } };

[Go Back~~](# LeetCode题解)

section8.2 滑动窗口#

1、无重复字符的最长子串#

Copy
class Solution { public: int lengthOfLongestSubstring(string s) { int ans = 0; unordered_map<char,int> hash; for(int last = 0, cur = 0;cur < s.size();cur++){ hash[s[cur]]++; while(hash[s[cur]] == 2){ hash[s[last++]]--; } ans = max(ans,cur-last+1); } return ans; } };

2、最小覆盖子串#

Copy
class Solution { public: string minWindow(string s, string t) { string ans = ""; unordered_map<char,int> hash; int cnt = 0; for(auto c:t) { if(!hash[c]) cnt++; hash[c]++; } for(int i=0,j=0,c=0;i<s.size();i++){ if(hash[s[i]] == 1) c++; hash[s[i]]--; while(c == cnt && hash[s[j]] < 0) hash[s[j++]]++; if(c == cnt) { if(ans.empty() || ans.size() > i-j+1) ans = s.substr(j,i-j+1); } } return ans; } };

3、长度最小的子数组#

Copy
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int ans = 0; for(int i=0,j=0,t=0;i<nums.size();i++){ t+=nums[i]; while(t >= target) { ans = ans == 0?i-j+1: min(ans,i-j+1); t-=nums[j++]; if(t >= target) ans = ans == 0?i-j+1: min(ans,i-j+1); } } return ans; } };

4、替换后的最长重复字符#

Copy
class Solution { public: int characterReplacement(string s, int k) { int ans = 0; for (char c='A'; c<='Z'; c++){ for(int i=0,j=0,cnt=0;i<s.size();i++){ if(s[i] == c) cnt++; while(i-j+1 - cnt > k){ if(s[j] == c) cnt--; j++; } ans = max(ans, i-j+1); } } return ans; } };

5、找到字符串中所有字母异位词#

Copy
class Solution { public: vector<int> findAnagrams(string s, string p) { int m=s.size(),n=p.size(); vector<int> res; if(n>m) return res; unordered_map<char,int> hash; for(auto&c:p)hash[c]++; int tot = hash.size(); for(int i=0,j=0,k=0;i<s.size();i++){ if(--hash[s[i]] == 0) k++; if(i - j + 1 > p.size()){ if(hash[s[j]] == 0) k--; hash[s[j++]]++; } if(k == tot) res.push_back(j); } return res; } };

6、数组中的 k-diff 数对#

Copy
// O(n) class Solution { public: int findPairs(vector<int>& nums, int k) { if(k<0) return 0; unordered_set<int> first_ele, hash; for(int i=0;i<nums.size();i++){ if(hash.find(nums[i] - k) != hash.end()) first_ele.insert(nums[i]-k); if(hash.find(nums[i] + k) != hash.end()) first_ele.insert(nums[i]); hash.insert(nums[i]); } return first_ele.size(); } }; // O(nlogn) class Solution { public: int findPairs(vector<int>& nums, int k) { int ans = 0; sort(nums.begin(), nums.end()); for(int i=0,j=0;i<nums.size();i++){ while(i+1<nums.size() && nums[i+1] == nums[i]) i++; while(j < i && nums[i] - nums[j] > k) j++; if(j < i && nums[i] - nums[j] == k) ans++; } return ans; } };

7、字符串的排列#

Copy
class Solution { public: bool checkInclusion(string s1, string s) { unordered_map<char,int> hash; for(auto c:s1) hash[c]++; int tot = hash.size(); for(int i=0, j=0, cnt = 0; i<s.size(); i++){ if(--hash[s[i]] == 0) cnt++; if(i-j+1 > s1.size()){ if(hash[s[j]] == 0) cnt--; hash[s[j++]]++; } if(cnt == tot) return true; } return false; } };

8、最大连续1的个数 III#

Copy
class Solution { public: int longestOnes(vector<int>& nums, int k) { int ans=0; for(int i=0,j=0,cnt=0;i<nums.size();i++){ if(nums[i] == 1) cnt++; if(i-j+1 - cnt <= k) ans = max(ans, i-j+1); while(i-j+1 - cnt > k){ if(nums[j++] == 1) cnt--; } } return ans; } };

9、删掉一个元素以后全为 1 的最长子数组#

Copy
class Solution { public: int longestSubarray(vector<int>& nums) { int res = 0; for(int l = 0 ,r = 0, cnt = 0;r<nums.size();r++){ if(nums[r]==0){ cnt++; } while(cnt>1){ if(nums[l]==0){ cnt--; } l++; } res = max(res,r-l+1); } return res-1; } };

10、删除子数组的最大得分#

Copy
class Solution { public: int maximumUniqueSubarray(vector<int>& nums) { int ans = 0; unordered_map<int,int> hash; for(int i=0,j=0,tot=0;i<nums.size();i++){ hash[nums[i]]++; tot+=nums[i]; while(hash[nums[i]] != 1){ hash[nums[j]]--; tot-=nums[j]; j++; } ans = max(ans,tot); } return ans; } };

[Go Back~~](# LeetCode题解)

section8.3 逆向双指针#

1、最长回文子串#

Copy
class Solution { public: string longestPalindrome(string s) { vector<int> t = {0,0}; for(int i = 0;i<s.size();i++){ int l = i,r = i; while(l >= 0 && r < s.size() && s[l] == s[r]){ if(t[1] - t[0] < (r-l+1)){ t[0] = l; t[1] = r; } l--; r++; } l = i-1;r = i; while(l >= 0 && r < s.size() && s[l] == s[r]){ if(t[1] - t[0] < (r-l+1)){ t[0] = l; t[1] = r; } l--; r++; } } return s.substr(t[0],t[1] - t[0] + 1); } };

2、盛最多水的容器#

Copy
class Solution { public: int maxArea(vector<int>& height) { int l = 0, r = height.size()-1, res = 0; while(l<r){ res = max(res, min(height[r] , height[l]) * (r - l)); if(height[l] < height[r]) l++; else r--; } return res; } };

3、三数之和#

Copy
class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> res; if(nums.size() < 3) return res; sort(nums.begin(),nums.end()); for(int i = 0;i<nums.size();i++){ if(i && nums[i] == nums[i-1]) continue; for(int j = i+1,k = nums.size()-1;j<k;){ if(j != i+1 && nums[j] == nums[j-1]) j++; else{ if(nums[j] + nums[k] < 0 - nums[i]) j++; else if(nums[j] + nums[k] > 0 - nums[i]) k--; else { res.push_back({nums[i],nums[j],nums[k]}); j++; } } } } return res; } };

4、最接近的三数之和#

Copy
class Solution { public: int threeSumClosest(vector<int>& nums, int target) { pair<int,int> pii(INT_MAX,INT_MAX); sort(nums.begin(),nums.end()); for(int i = 0;i<nums.size()-2;i++){ for(int j = i+1,k=nums.size()-1;j<k;){ int t = nums[j] + nums[k] + nums[i]; if(t < target){ j++; pii = min(pii,make_pair(abs(target - t),t)); }else if(t > target){ k--; pii = min(pii,make_pair(abs(target - t),t)); }else return target; } } return pii.second; } };

5、四数之和#

Copy
class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { vector<vector<int>> res; if(nums.size() < 4) return res; sort(nums.begin(),nums.end()); for(int i = 0;i<nums.size();i++){ if(i != 0 && nums[i-1] == nums[i]) continue; for(auto j = i+1;j<nums.size();j++){ if(j != i+1 && nums[j-1] == nums[j]) continue; int l = j+1, r = nums.size()-1; while(l<r){ long long sum = nums[i]; sum += nums[j]; sum += nums[l]; sum += nums[r]; if(sum == target){ res.push_back({nums[i] ,nums[j] ,nums[l] ,nums[r]}); do{l ++;} while(l < r && nums[l] == nums[l - 1]); do{r --;} while(l < r && nums[r] == nums[r + 1]); }else if(sum < target) l++; else r--; } } } return res; } };

6、验证回文串#

Copy
class Solution { public: bool isPalindrome(string s) { int l = 0, r = s.size()-1; while(l<r){ if(!isalnum(s[l]) && !isalpha(s[l])) {l++; continue; } if(!isalnum(s[r]) && !isalpha(s[r])) {r--; continue; } if(s[l] == s[r] || (abs(s[l] - s[r]) == 'a'-'A') && isalpha(s[l]) && isalpha(s[r])){ l++,r--; }else return false; } return true; } };

7、两数之和 II - 输入有序数组#

Copy
class Solution { public: vector<int> twoSum(vector<int>& numbers, int target) { for(int i = 0,j = numbers.size()-1;i<j;){ if(numbers[i] + numbers[j] > target) j--; if(numbers[i] + numbers[j] < target) i++; if(numbers[i] + numbers[j] == target) return{i+1,j+1}; } return {-1,-1}; } };

8、反转字符串#

Copy
class Solution { public: void reverseString(vector<char>& s) { for(int l = 0, r = s.size()-1;l<r;){ swap(s[l],s[r]); l++; r--; } } };

9、反转字符串中的元音字母#

Copy
class Solution { public: bool is(char c) { if(c=='a' || c=='e' || c=='i' || c=='o' || c=='u' || c=='A' || c=='E' || c=='I' || c=='O' || c=='U' ) return true; else return false; } string reverseVowels(string s) { string ans = s; for(int l=0,r=s.size()-1;l<r;){ while(l<r && !is(ans[l])) l++; while(r>l && !is(ans[r])) r--; swap(ans[l], ans[r]); l++; r--; } return ans; } };

[Go Back~~](# LeetCode题解)

chap-9:哈希表#

1、字母异位词分组#

Copy
class Solution { public: vector<vector<string>> groupAnagrams(vector<string>& strs) { unordered_map<string,vector<string>> hash; for(auto &str:strs){ string s = str; sort(s.begin(),s.end()); if(hash.find(s) != hash.end()){ hash[s].emplace_back(str); }else{ hash[s] = vector<string>({str}); } } vector<vector<string>> ans; for(auto &iter:hash){ ans.emplace_back(iter.second); } return ans; } };

2、最长连续序列#

Copy
class Solution { public: int longestConsecutive(vector<int>& nums) { unordered_set<int> s(nums.begin(),nums.end()); int ans = 0; for(auto& num:s){ if(s.find(num - 1) == s.end()){ int st = num; while(s.find(++st) != s.end()); ans = max(st - num,ans); } } return ans; } }; // 法2 class Solution { public: int longestConsecutive(vector<int>& nums) { unordered_map<int,int> right,left; int ans = 0; for(auto &num:nums){ int l = right[num-1]; // right:表示以x为右终点 int r = left[num+1]; // left:表示以x为左起点 right[num+r] = max(right[num+r], l+r+1); left[num-l] = max(left[num-l], l+r+1); ans = max(ans, l+r+1); } return ans; } };

3、存在重复元素#

Copy
class Solution { public: bool containsDuplicate(vector<int>& nums) { unordered_set<int> v; for (int i = 0; i < nums.size(); i++) { if (v.find(nums[i]) != v.end()) return true; v.insert(nums[i]); } return false; } };

4、存在重复元素 II#

Copy
class Solution { public: bool containsNearbyDuplicate(vector<int>& nums, int k) { unordered_map<int,int> hash; for(int i=0;i<nums.size();i++){ if(hash.find(nums[i]) != hash.end()){ if(i - hash[nums[i]] <= k) return true; else hash[nums[i]] = i; }else hash[nums[i]] = i; } return false; } };

5、存在重复元素 III#

Copy
class Solution { public: bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) { typedef long long ll; multiset<ll> hash; hash.insert(1e18); hash.insert(-1e18); for(int i=0,j=0;i<nums.size();i++){ if(i-j > k){ hash.erase(hash.find(nums[j++])); } int x = nums[i]; auto it = hash.lower_bound(x); if(*it - x <= t) return true; it--; if(x - *it <= t) return true; hash.insert(x); } return false; } };

6、猜数字游戏#

Copy
class Solution { public: string getHint(string secret, string guess) { unordered_map<char,int> hash; for(auto c:secret) hash[c]++; int tot=0, bulls=0; for(int i=0;i<guess.size();i++){ if(secret[i] == guess[i]) bulls++; if(hash[guess[i]]){ tot++; hash[guess[i]]--; } } return to_string(bulls)+"A"+to_string(tot-bulls)+"B"; } };

7、两个数组的交集#

Copy
class Solution { public: vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { unordered_set<int> n1(nums1.begin(), nums1.end()); vector<int> ans; for(auto x:nums2){ if(n1.count(x)) { ans.push_back(x); n1.erase(x); } } return ans; } };

8、两个数组的交集 II#

Copy
class Solution { public: vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { unordered_multiset<int> S; vector<int> res; for (int x : nums1) S.insert(x); for (int x : nums2) if (S.count(x)) { res.push_back(x); S.erase(S.find(x)); } return res; } };

9、O(1) 时间插入、删除和获取随机元素#

Copy
class RandomizedSet { public: vector<int> temp; unordered_map<int,int> hash; int cnt = 0; RandomizedSet() { } bool insert(int val) { if(hash.find(val) == hash.end()){ hash[val] = cnt++; temp.push_back(val); return true; } else return false; } bool remove(int val) { auto it = hash.find(val); if(it != hash.end()){ int idx = it->second; temp[idx] = temp.back(); hash[temp[idx]] = idx; temp.pop_back(); cnt--; hash.erase(it); return true; }else return false; } int getRandom() { return temp[rand()%cnt]; } };

10、O(1) 时间插入、删除和获取随机元素 - 允许重复#

Copy
class RandomizedCollection { public: vector<int> num; unordered_map<int,unordered_set<int>> hash; RandomizedCollection() { } bool insert(int val) { bool f = hash.find(val) == hash.end(); num.push_back(val); hash[val].insert(num.size()-1); return f; } bool remove(int val) { if(hash.find(val) != hash.end()){ if(num.back() == val){ hash[val].erase(hash[val].find(num.size()-1)); num.pop_back(); if (hash[val].empty()) hash.erase(val); return true; } int t = *hash[val].begin(); hash[num.back()].erase(num.size() - 1); hash[num.back()].insert(t); swap(num[t], num.back()); num.pop_back(); hash[val].erase(t); if (hash[val].empty()) hash.erase(val); return true; } return false; } int getRandom() { return num[rand() % num.size()]; } };

11、赎金信#

Copy
class Solution { public: bool canConstruct(string ransomNote, string magazine) { if(magazine.size() < ransomNote.size()) return false; unordered_map<char,int> hash; for(auto c:magazine) hash[c]++; for(auto c:ransomNote){ if(hash[c] == 0) return false; else hash[c]--; } return true; } };

12、字符串中的第一个唯一字符#

Copy
class Solution { public: int firstUniqChar(string s) { unordered_map<char,int> hash; for(auto c:s) hash[c]++; for(int i=0;i<s.size();i++) if(hash[s[i]] == 1) return i; return -1; } };

13、最长回文串#

Copy
class Solution { public: int longestPalindrome(string s) { unordered_map<char,int> hash; for(auto c:s) hash[c]++; int ans = 0; bool f = false; for(auto &it:hash){ if(it.second % 2){ if(!f) f = true; ans+=it.second-1; }else ans+=it.second; } if(f) return ans+1; else return ans; } };

14、路径总和 III#

Copy
class Solution { public: int res = 0; unordered_map<int,int> cnt; int pathSum(TreeNode* root, int t) { cnt[0] = 1; dfs(root,t,0); return res; } void dfs(TreeNode*root,int t,int cur_sum){ if(root == nullptr) return; cur_sum += root->val; res += cnt[cur_sum - t]; cnt[cur_sum]++; dfs(root->left,t,cur_sum); dfs(root->right,t,cur_sum); cnt[cur_sum]--; } };

15、四数相加 II#

Copy
class Solution { public: int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) { unordered_map<int,int> hash; for(int i=0;i<nums1.size();i++){ for(int j=0;j<nums1.size();j++) hash[nums1[i]+nums2[j]]++; } int ans = 0; for(int i=0;i<nums1.size();i++){ for(int j=0;j<nums1.size();j++){ if(hash.find(-nums3[i]-nums4[j]) != hash.end()) ans+=hash[-nums3[i]-nums4[j]]; } } return ans; } };

16、和为 K 的子数组【×】#

Copy
class Solution { public: int subarraySum(vector<int>& nums, int k) { int ans=0,tot=0; unordered_map<int,int> hash; hash[0]=1; for(auto &x:nums){ tot+=x; ans+=hash[tot-k]; hash[tot]++; } return ans; } }; //通俗做法-超时O(n2) class Solution { public: int subarraySum(vector<int>& nums, int k) { int ans = 0; for(int i=0;i<nums.size();i++){ int sum = 0; for(int j=i;j>=0;j--){ sum+=nums[j]; if(sum == k) ans++; } } return ans; } };

17、LRU 缓存机制【×】#

Copy
class LRUCache { public: struct Node{ int key, val; Node* left; Node* right; Node(int _key, int _val): key(_key), val(_val), left(nullptr), right(nullptr){} }*L, *R; unordered_map<int, Node*> hash; int n; void remove(Node *p){ p->left->right = p->right; p->right->left = p->left; } void insert(Node *p){ p->right = L->right; p->left = L; L->right->left = p; L->right = p; } LRUCache(int capacity) { n = capacity; L = new Node(-1,-1); R = new Node(-1,-1); L->right = R; R->left = L; } int get(int key) { if(hash.find(key) == hash.end()) return -1; auto p = hash[key]; remove(p); // 先后顺序搞清 insert(p); return p->val; } void put(int key, int value) { if(hash.find(key)!=hash.end()){ auto p = hash[key]; p->val = value; remove(p); insert(p); }else{ if(hash.size() == n){ auto p = R->left; remove(p); hash.erase(p->key); delete p; } auto q = new Node(key, value); insert(q); hash[key] = q; } } };

18、LFU 缓存#

Copy
class LFUCache { public: struct Node{ Node *left, *right; int key, val; Node(int _key,int _val):key(_key), val(_val), left(NULL), right(NULL){} }; struct Block{ Block *left,*right; Node *head,*tail; int cnt; ~Block(){ delete head; delete tail; } Block(int _cnt){ cnt = _cnt; left = right = NULL; head = new Node(-1,-1); tail = new Node(-1,-1); head->right = tail, tail->left = head; } void insert(Node *p){ p->right = head->right; head->right->left = p; p->left = head; head->right = p; } void remove(Node *p){ p->left->right = p->right; p->right->left = p->left; } bool empty(){ return head->right == tail; } }*head,*tail; int n; unordered_map<int, Block*> hash_block; unordered_map<int, Node*> hash_node; void insert(Block *p){ // 在p的右侧插入新块,cnt是p->cnt + 1 auto cur = new Block(p->cnt + 1); cur->right = p->right; p->right->left = cur; p->right = cur; cur->left = p; } void remove(Block* p) { p->left->right = p->right; p->right->left = p->left; delete p; } LFUCache(int capacity) { n = capacity; head = new Block(0), tail = new Block(INT_MAX); head->right = tail, tail->left = head; } int get(int key) { if(hash_block.find(key) == hash_block.end()) return -1; auto block = hash_block[key]; auto node = hash_node[key]; block->remove(node); if (block->right->cnt != block->cnt + 1) insert(block); block->right->insert(node); hash_block[key] = block->right; if (block->empty()) remove(block); return node->val; } void put(int key, int value) { if(!n) return; // 特例 if(hash_block.find(key) != hash_block.end()){ hash_node[key]->val = value; get(key); } else{ if (hash_block.size() == n) { auto p = head->right->tail->left; head->right->remove(p); if (head->right->empty()) remove(head->right); hash_block.erase(p->key); hash_node.erase(p->key); delete p; } auto p = new Node(key, value); if (head->right->cnt > 1) insert(head); head->right->insert(p); hash_block[key] = head->right; hash_node[key] = p; } } };

19、连续的子数组和【×】前缀和+哈希表#

Copy
class Solution { public: bool checkSubarraySum(vector<int>& nums, int k) { int n = nums.size(); vector<int> s(n+1); for(int i=1;i<=n;i++) s[i] = s[i-1]+nums[i-1]; unordered_set<int> hash; for(int i =2;i<=n;i++){ hash.insert(s[i-2]%k); if(hash.count(s[i]%k)) return true; } return false; } };

20、连续数组【×】#

Copy
class Solution { public: int findMaxLength(vector<int>& nums) { int ans = 0; unordered_map<int,int>hash; hash[0] = 0; for(int i=1,x=0;i<=nums.size();i++){ x+=(nums[i-1] == 1?1:-1); if(hash.count(x)) ans = max(ans,i-hash[x]); else hash[x]=i; } return ans; } };

21、数组中的 k-diff 数对#

Copy
class Solution { public: int findPairs(vector<int>& nums, int k) { unordered_set<int> hash, ele; for(int i=0;i<nums.size();i++){ if(hash.find(nums[i] + k) != hash.end()) ele.insert(nums[i]); if(hash.find(nums[i] - k) != hash.end()) ele.insert(nums[i] - k); hash.insert(nums[i]); } return ele.size(); } };

22、砖墙【×】#

Copy
class Solution { public: int leastBricks(vector<vector<int>>& wall) { int width = accumulate(wall[0].begin(), wall[0].end(), 0); unordered_map<int,int> hash; int sum; for(auto &a:wall){ sum = 0; for(auto& b:a) sum+=b, hash[sum]++; } sum=0; for(auto &it:hash){ if(it.first != width) sum = max(sum,it.second); } return wall.size() - sum; } };

23、分糖果#

Copy
class Solution { public: int distributeCandies(vector<int>& candyType) { unordered_set<int> hash(candyType.begin(), candyType.end()); return min(candyType.size()/2, hash.size()); } };

24、设计哈希映射【×】#

Copy
// 开放寻址法 class MyHashMap { public: const static int N=20011; int hash_key[N], hash_val[N]; MyHashMap() { memset(hash_key,-1,sizeof(hash_key)); } int find(int key){ int t = key%N; while(hash_key[t] != key && hash_key[t] != -1) if(++t == N) t = 0; return t; } void put(int key, int value) { int t = find(key); hash_key[t] = key; hash_val[t] = value; } int get(int key) { int t = find(key); if(hash_key[t] == -1) return -1; return hash_val[t]; } void remove(int key) { int t = find(key); if (hash_key[t] != -1) hash_key[t] = -2; } };

25、设计哈希集合#

Copy
// 拉链法 class MyHashSet { public: const static int N = 20011; vector<int> help[N]; MyHashSet() { } int find(vector<int>&h, int key){ for(int i=0;i<h.size();i++) if(h[i] == key) return i; return -1; } void add(int key) { int t = key%N; int k = find(help[t], key); if(k == -1) help[t].emplace_back(key); } void remove(int key) { int t = key%N; int k = find(help[t], key); if(k != -1){ help[t].erase(help[t].begin()+k); } } bool contains(int key) { int t = key%N; return find(help[t], key) != -1; } };

26、数的平方等于两数乘积的方法数#

Copy
class Solution { public: int numTriplets(vector<int>& nums1, vector<int>& nums2) { typedef long long ll; unordered_map<ll,int> hash; for(auto num:nums1) hash[(ll)num*num]++; int ans = 0; for(int i=0;i<nums2.size();i++){ for(int j=i-1;j>=0;j--){ if(hash.count((ll)nums2[i]*nums2[j])) ans+=hash[(ll)nums2[i]*nums2[j]]; } } unordered_map<ll,int> hash1; for(auto num:nums2) hash1[(ll)num*num]++; for(int i=0;i<nums1.size();i++){ for(int j=i-1;j>=0;j--){ if(hash1.count((ll)nums1[i]*nums1[j])) ans+=hash1[(ll)nums1[i]*nums1[j]]; } } return ans; } };

27、警告一小时内使用相同员工卡大于等于三次的人#

Copy
class Solution { public: vector<string> alertNames(vector<string>& keyName, vector<string>& keyTime) { unordered_map<string,vector<int>> hash; for(int i=0;i<keyName.size();i++){ int hh,mm; sscanf(keyTime[i].c_str(),"%d:%d",&hh,&mm); hash[keyName[i]].push_back(hh*60+mm); } vector<string> ans; for(auto &it:hash){ sort(it.second.begin(),it.second.end()); for(int i=2;i<it.second.size();i++){ if(it.second[i] - it.second[i-2] <= 60){ ans.push_back(it.first); break; } } } sort(ans.begin(), ans.end()); return ans; } };

28、字符频次唯一的最小删除次数#

Copy
class Solution { public: int minDeletions(string s) { vector<int> help(26); for(auto c:s) help[c-'a']++; sort(help.rbegin(), help.rend()); int ans = 0; for(int i=0;i<help.size()-1;i++){ if(help[i] > help[i+1]) continue; if(help[i] == 0){ ans += help[i+1]; help[i+1] = 0; }else{ int a = help[i]-1; ans += help[i+1] - a; help[i+1] = a; } } return ans; } };

29、K 和数对的最大数目#

Copy
class Solution { public: int maxOperations(vector<int>& nums, int k) { unordered_map<int,int> hash; for(auto t:nums) hash[t]++; int ans = 0; for(auto &t:hash){ if(hash.find(k - t.first) != hash.end()){ if(k - t.first == t.first) ans += t.second-1; else ans += min(t.second, hash[k - t.first]); } } return (ans+1)/2; // } };

30、同构字符串【双射】#

Copy
class Solution { public: bool isIsomorphic(string s, string t) { unordered_map<char,char> hashs; unordered_map<char,char> hasht; for(auto i=0;i<s.size();i++){ if(hashs.count(t[i])) if(hashs[t[i]] == s[i]) continue; else return false; else hashs[t[i]] = s[i]; if(hasht.count(s[i])) if(hasht[s[i]] == t[i]) continue; else return false; else hasht[s[i]] = t[i]; } return true; } };

31、单词规律#

Copy
class Solution { public: bool wordPattern(string t, string s) { stringstream sstream(s); unordered_map<char,string> ts; unordered_map<string,char> st; int i = 0; while(sstream){ string tt; sstream>>tt; if(ts.count(t[i])){ if(ts[t[i]] != tt) return false; }else ts[t[i]] = tt; if(st.count(tt)){ if(st[tt] != t[i]) return false; }else st[tt] = t[i]; i++; } return i == (t.size()+1); } };

[Go Back~~](# LeetCode题解)

posted @   SrtFrmGNU  阅读(46)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示
CONTENTS