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

posted @ 2022-02-14 01:21  SrtFrmGNU  阅读(38)  评论(0编辑  收藏  举报