【leetcode】栈题目总结

发布于:2024-05-10 ⋅ 阅读:(28) ⋅ 点赞:(0)

 普通栈

先进后出的特点

​​​​​​20. 有效的括号

class Solution {
public:
    unordered_map<char, char> mp = {
        {')', '('},
        {']', '['},
        {'}', '{'}
    };

    bool isValid(string s) {
        stack<char> st;
        for (char c : s) {
            if (c == '(' || c == '[' || c == '{') {
                st.push(c);
            } else {
                if (!st.empty() && mp[c] == st.top()) {
                    st.pop();
                } else {
                    return false;
                }
            }
        }
        return st.empty();
    }
};

155. 最小栈

class MinStack {
private:
    stack<int> xStack; // 存放正常数据
    stack<int> minStack; // 顺序存放元素对应的最小值
public:
    MinStack() {

    }
    
    void push(int val) {
        xStack.push(val);
        if (!minStack.empty()) {
            minStack.push(min(minStack.top(), val));
        } else {
            minStack.push(val);
        }
    }
    
    void pop() {
        xStack.pop();
        minStack.pop();
    }
    
    int top() {
        return xStack.top();
    }
    
    int getMin() {
        return minStack.top();
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(val);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

946. 验证栈序列

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        stack<int> st;
        for (int i = 0, j = 0; i < pushed.size(); ++i) {
            st.push(pushed[i]);
            while (!st.empty() && st.top() == popped[j]) {
                st.pop();
                ++j;
            }
        }
        return st.empty();
    }
};

394. 字符串解码

class Solution {
public:
    string getDigits(string& s, int& ptr) {
        string res;
        while (isdigit(s[ptr])) {
            res.push_back(s[ptr++]);
        }
        return res;
    }

    string getString(vector<string> &v) {
        string ret;
        for (const auto &s: v) {
            ret += s;
        }
        return ret;
    }

    string decodeString(string s) {
        vector<string> stk;
        int ptr = 0;

        while (ptr < s.size()) {
            char cur = s[ptr];
            if (isdigit(cur)) {
                string digits = getDigits(s, ptr);
                stk.push_back(digits);
            } else if (isalpha(cur) || cur == '[') {
                stk.push_back(string(1, cur));
                ptr++;
            } else {
                ptr++;
                vector<string> sub;
                while (stk.back() != "[") {
                    sub.push_back(stk.back());
                    stk.pop_back();
                }
                stk.pop_back();
                int repTIme = stoi(stk.back());
                stk.pop_back();

                string subStr;
                while (!sub.empty()) {
                    subStr += sub.back();
                    sub.pop_back();
                }

                string tmp;
                while (repTIme--) {
                    tmp += subStr;
                }
                stk.push_back(tmp);
            }
        }
        return getString(stk);
    }
};

单调栈

单调栈用途不太广泛,只处理一类典型的问题,比如「下一个更大元素」,「上一个更小元素」等。

739. 每日温度

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        // 单调递减栈,即从底到顶逐渐递减
        stack<int> st;
        vector<int> res(temperatures.size());

        for (int i = 0; i< temperatures.size(); ++i) {
            while (!st.empty() && temperatures[i] > temperatures[st.top()]) {
                int preIndex = st.top();
                res[preIndex] = i - preIndex;
                st.pop();
            }
            st.push(i);
        }
        return res;
    }
};

496. 下一个更大元素 I

双数组

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        stack<int> st;
        unordered_map<int, int> mp;
        vector<int> res;

        for (int i = 0; i <  nums2.size(); ++i) {
            while (!st.empty() && nums2[i] > st.top()) {
                int preVal = st.top();
                st.pop();
                mp[preVal] = nums2[i];
            }
            st.push(nums2[i]);
        }

        for (auto num : nums1) {
            if (mp.find(num) != mp.end()) {
                res.push_back(mp[num]);
            } else {
                res.push_back(-1);
            }
        }
        return res;
    }
};

503. 下一个更大元素 II

循环数组

class Solution {
public:
    vector<int> nextGreaterElements(vector<int>& nums) {
        int len = nums.size();
        
        stack<int> st;
        vector<int> res(len, -1);

        
        for (int i = 0; i <  2 * len; ++i) {
            int index = i % len;
            while (!st.empty() && nums[index] > nums[st.top()]) {
                int preIndex= st.top();
                st.pop();
                res[preIndex] = nums[index];
            }
            st.push(index);
        }

        return res;
    }
};

84. 柱状图中最大的矩形

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        stack<int> st;

        // 假设 h=heights[i]是矩形的高度,那么矩形的宽度最大是多少?我们需要知道:
        // 1. 在 i 左侧的小于 h 的最近元素的下标 left
        // 2. 在 i 右侧的小于 h 的最近元素的下标 right
        vector<int> left(n, 0), right(n, n);

        for (int i = 0; i < n; ++i) {
            while (!st.empty() && heights[i] < heights[st.top()]) {
                int index = st.top();
                st.pop();
                right[index] = i;
            }
            left[i] = st.empty() ? -1 : st.top();
            st.push(i);
        }

        int res = 0;
        for (int i = 0; i < n; ++i) {
            int height = heights[i];
            int wide = right[i] - left[i] - 1;
            res = max(res, height * wide);
        }
        return res;
    }
};

42. 接雨水

单调栈解法:

【Leetcode每日打卡】接雨水问题的超完全手册 - 知乎 (zhihu.com)

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> st;
        int res = 0;

        for (int i = 0; i < height.size(); ++i) {
            while (!st.empty() && height[i] > height[st.top()]) {
                int bottomIndex = st.top();
                st.pop();
                while (!st.empty() && height[bottomIndex] == height[st.top()]) {
                    st.pop();
                }

                if (!st.empty()) {
                    int heightDiff = min(height[st.top()], height[i]) - height[bottomIndex];
                    int wide = i - st.top() - 1;
                    res += heightDiff * wide;
                }
                
            }
            st.push(i);
        }
        return res;
    }
};

动态规划解法:找到第i个元素左右最大的值得较小值,减去当前高度,即为该列能存储的雨水

class Solution {
public:
    int trap(vector<int>& height) {
        int len = height.size();
        int sum = 0;

        vector<int> left_h(height.size());
        vector<int> right_h(height.size());

        for (int i = 1; i < len; ++i) {
            left_h[i] = max(left_h[i-1], height[i-1]);
        }

        for (int j = len - 2; j >= 0; --j) {
            right_h[j] = max(right_h[j+1], height[j+1]);
        }

        for (int i = 1; i < len - 1; ++i) {
            int min_h = min(left_h[i], right_h[i]);
            if (min_h > height[i]) {
                sum += min_h - height[i];
            }
        }
        return sum;
    }
};

双指针解法:

class Solution {
public:
    int trap(vector<int>& height) {
        int len = height.size();
        int sum = 0;
        int left = 0, right = len - 1;
        int left_max = 0, right_max = 0;

        while (left < right) {
            if (height[left] < height[right]) {
                if (left_max <= height[left]) {
                    left_max = height[left];
                } else {
                    sum += left_max - height[left];
                }
                ++left;
            } else {
                if (right_max <= height[right]) {
                    right_max = height[right];
                } else {
                    sum += right_max - height[right];
                }
                --right;
            }
        }
        return sum;
    }
};


网站公告

今日签到

点亮在社区的每一天
去签到