栈-核心基础算法题总结(c++)

27 篇文章 0 订阅

目录

1. 有效的括号

2. 最小栈

3. 回文链表


1. 有效的括号

https://leetcode-cn.com/problems/valid-parentheses/

思路:栈, 左括号进,右括号出 

class Solution {
public:
    bool isValid(string s) {
        // 1.初始化准备
        stack<char> stk;
        unordered_map<char, char> mp = {
            {'(', ')'},
            {'[', ']'},
            {'{', '}'}
        };

        // 2.正式遍历
        for (const auto &c : s) {
            if (mp.count(c) != 0) {
                stk.push(c);
            }
            else if (stk.empty() || mp[stk.top()] != c) {
                return false;
            }
            else {
                stk.pop();
            }
        }
        // 3.后处理
       return stk.empty();
    }
};

时间复杂度O(n), 空间复杂度O(n)

2. 最小栈

https://leetcode-cn.com/problems/min-stack/

思路:使用辅助栈

class MinStack {
private:
    vector<int> stk;
    vector<int> vmin;
public:
    /** initialize your data structure here. */
    MinStack() {

    }
    
    void push(int val) {
        stk.push_back(val);
        if (vmin.empty() || vmin.back() > val) {
            vmin.push_back(val);
        }
        else {
            vmin.push_back(vmin.back());
        }
    }
    
    void pop() {
        stk.pop_back();
        vmin.pop_back();
    }
    
    int top() {
        return stk.back();
    }
    
    int getMin() {
        return vmin.back();
    }
};

/**
 * 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();
 */

时间复杂度O(1), 空间复杂度O(n) 

3. 回文链表

https://leetcode-cn.com/problems/palindrome-linked-list/

思路: 可以使用栈, 两次遍历

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        // 1.初始化准备
        stack<int> stk;

        // 2.第一次遍历,压栈
        ListNode* curr = head;
        while (curr) {
            stk.push(curr->val);
            curr = curr->next;
        }

        // 3.第二次遍历,出栈并检查
        curr = head;
        while (curr) {
            if (curr->val != stk.top()) {
                return false;
            }
            else {
                stk.pop();
            }
            curr = curr->next;
        }

        return true;
    }
};

时间复杂度O(n), 空间复杂度O(n)

4. 单调栈

直方图中最大矩形面积

解法一:暴力解法

class Solution {
public:
    // 暴力解法:遍历每一个柱子,向两边找小于该柱子高度的柱子,最终可以确定矩形宽度
    // 然后求出最大值, 会超时
    int largestRectangleArea(vector<int>& heights) {
        int ans = 0;
        for (int i=0; i<heights.size(); ++i) {
            int left = i;
            int right = i;
            while (left >= 0 && heights[left] >= heights[i]) {
                --left;
            }
            left = left == -1 ? 0 : (left+1);

            while (right < heights.size() && heights[right] >= heights[i]) {
                ++right;
            }
            right = right == heights.size() ? (heights.size() - 1) : (right - 1);

            int width = right - left + 1;
            int area = heights[i] * width;
            if (area > ans) {
                ans = area;
            }
        }

        return ans;
    }
};

时间复杂度O(n^2),空间复杂O(1) 

解法二:单调栈

关键点:

  • 利用辅助前后哨兵就不用处理空栈的特殊情况,以及不用对最后的栈做特殊处理
  • 最核心的是矩形宽的计算,等于当前索引检索减少该栈中去前一个的元素,再减去1
class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        // 1.为了简化栈处理,设置前后哨兵,
        // 这样不会有空栈,而且最后也不用对剩余栈进行特殊处理
        vector<int> new_heights;
        new_heights.push_back(-1);
        for (auto &m : heights) {
            new_heights.push_back(m);
        }
        new_heights.push_back(-1);

        // 2.正式遍历处理
        stack<int> stk; //单调不减栈,存放的是索引,因为索引需要用到,同时高度可以通过数组索引得到
        int ans = 0; //存放结果
        stk.push(0); //栈首个元素为索引0
        for (int i=1; i<new_heights.size(); ++i) {
            // 2.1 当前高度大于等于栈顶高度
            if (new_heights[i] >= new_heights[stk.top()]) {
                stk.push(i);
            }
            // 2.2 当前高度小于栈顶高度
            else {
                while (new_heights[i] < new_heights[stk.top()]) {
                    // 关键的是宽的计算:等于当前索引检索减少该栈中去前一个的索引,再减去1
                    int top = stk.top();
                    stk.pop();
                    int area = new_heights[top] * (i - stk.top() - 1);
                    ans = area > ans ? area : ans;
                }
                stk.push(i);
            }
        }

        return ans;
    }
};

时间复杂度O(n)(每个元素进出栈一次),空间复杂度O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值