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


    目录

    LeetCode题解

    chap-7: 栈、队列

    1、最小栈【设计】

    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、比较含退格的字符串

    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、设计一个支持增量操作的栈 【×】

    // 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、设计循环队列

    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、设计循环双端队列

    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、验证栈序列

    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、删除字符串中的所有相邻重复项

    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

    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、用队列实现栈

    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、用栈实现队列

    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、接雨水

    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、柱状图中最大的矩形

    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、最大矩形

    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

    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【破环成链】

    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、每日温度

    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、滑动窗口最大值

    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、逆波兰表达式求值

    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、基本计算器【×】

    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

    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、有效的括号

    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、最长有效括号

    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、外观数列【模拟】

    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、最后一个单词的长度

    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、删除有序数组中的重复项

    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

    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、移除元素

    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、颜色分类

    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、合并两个有序数组

    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、移动零

    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、判断子序列

    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、字符串中的单词数

    // 库函数
    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、压缩字符串

    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 的个数

    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、划分字母区间[×]

    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

    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、区间列表的交集

    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、无重复字符的最长子串

    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、最小覆盖子串

    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、长度最小的子数组

    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、替换后的最长重复字符

    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、找到字符串中所有字母异位词

    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 数对

    // 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、字符串的排列

    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

    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 的最长子数组

    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、删除子数组的最大得分

    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、最长回文子串

    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、盛最多水的容器

    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、三数之和

    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、最接近的三数之和

    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、四数之和

    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、验证回文串

    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 - 输入有序数组

    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、反转字符串

    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、反转字符串中的元音字母

    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、字母异位词分组

    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、最长连续序列

    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、存在重复元素

    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

    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

    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、猜数字游戏

    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、两个数组的交集

    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

    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) 时间插入、删除和获取随机元素

    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) 时间插入、删除和获取随机元素 - 允许重复

    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、赎金信

    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、字符串中的第一个唯一字符

    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、最长回文串

    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

    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

    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 的子数组【×】

    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 缓存机制【×】

    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 缓存

    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、连续的子数组和【×】前缀和+哈希表

    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、连续数组【×】

    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 数对

    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、砖墙【×】

    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、分糖果

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

    24、设计哈希映射【×】

    // 开放寻址法
    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、设计哈希集合

    // 拉链法
    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、数的平方等于两数乘积的方法数

    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、警告一小时内使用相同员工卡大于等于三次的人

    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、字符频次唯一的最小删除次数

    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 和数对的最大数目

    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、同构字符串【双射】

    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、单词规律

    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题解)

  • 相关阅读:
    js创建json对象
    redis命令行清缓存
    查询某个用户所有新增的用户,本月新增用户,上个月新增的用户
    js处理el表达式
    调用上一个页面的js方法
    生成唯一code
    jeeplus中两个项目redis冲突问题
    $ 与 #
    字典表的维护
    将html文档转成pdf
  • 原文地址:https://www.cnblogs.com/SrtFrmGNU/p/15891052.html
Copyright © 2020-2023  润新知