栈——从LeetCode题海中总结常见套路

首先记住这句话,笔试都遇到好几次了:

从数据结构角度看,栈也是线性表!

目录

Leetcode150.逆波兰表达式求值

LeetCode1021.删除最外层的括号

LeetCode921.使括号有效的最少添加

LeetCode1047.删除字符串中的所有相邻重复项

LeetCode面试题03.04.化栈为队

LeetCode682.棒球比赛

LeetCode496.下一个更大的元素I


Leetcode150.逆波兰表达式求值

最经典的一道栈的题目,想当年为了弄懂这题可是花了不少劲,现在看来实属easy!

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(int i=0;i<tokens.size();i++){
                if(tokens[i]=="+"){
                        int a = st.top();
                        st.pop();
                        int b = st.top();
                        st.pop();
                        st.push(a+b);
                }else if(tokens[i]=="-"){
                        int a = st.top();
                        st.pop();
                        int b = st.top();
                        st.pop();
                        st.push(b-a);
                }else if(tokens[i]=="*"){
                        int a = st.top();
                        st.pop();
                        int b = st.top();
                        st.pop();
                        st.push(a*b);
                }else if(tokens[i]=="/"){
                        int a = st.top();
                        st.pop();
                        int b = st.top();
                        st.pop();
                        st.push(b/a);
                }else{
                        st.push(stoi(tokens[i]));
                }
        }
        return st.top();
    }
};

LeetCode1021.删除最外层的括号

这题真妙啊,要不是看了评论区,怎么也不会想到可以用栈来求解!

class Solution {
public:
	string removeOuterParentheses(string S) {
		string res = "";
		stack<char> mystack;
		for (int i = 0; i < S.size(); i++) {
			if (S[i] == ')')
				mystack.pop();
			if (!mystack.empty())
				res+=S[i];
			if (S[i] == '(')
				mystack.push('(');
		}
		return res;
	}
};

LeetCode921.使括号有效的最少添加

这题是上面那题的姊妹版,同样用栈stack解决,但是注意先判断栈是否为空!

class Solution {
public:
    int minAddToMakeValid(string S) {
        stack<char> s;
        for(int i=0;i<S.size();i++){
            if(S[i]=='('||s.empty())//先判断栈是否为空
                s.push(S[i]);
            else if(S[i]==')'&&s.top()=='(')
                s.pop();
            else
                s.push(S[i]);
        }
        return s.size();
    }
};

LeetCode1047.删除字符串中的所有相邻重复项

想一下没有再比这个更明显的栈结构模拟的了……

进阶一点的逆波兰算法:栈解逆波兰算法

class Solution {
public:
    string removeDuplicates(string S) {
        stack<char> s;
        s.push(-1);//开头放进一个不可能的元素放置后面地址错误
        for(int i=0;i<S.size();i++){
            if(S[i]!=s.top())
                s.push(S[i]);
            else
                s.pop();
        }
        string ss;
        int size = s.size();
        for(int i=0;i<size-1;i++){
            ss.push_back(s.top());
            s.pop();
        }
        reverse(ss.begin(),ss.end());//结果需要反转
        return ss;
    }
};

LeetCode面试题03.04.化栈为队

用两个栈来模拟队列,是一个十分经典的栈与队列问题!

class MyQueue {
public:
    /** Initialize your data structure here. */
    stack<int> s1,s2;//s1记录队列的压入顺序,s2作转换使用
    MyQueue() {

    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
    //因为每次pop或者peek的时候都改变了s1,所以push的时候要将s2中的倒回s1
        while(!s2.empty()){
            s1.push(s2.top());
            s2.pop();
        }
        s1.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        while(!s1.empty()){
            s2.push(s1.top());
            s1.pop();
        }
        int ans = s2.top();
        s2.pop();
        return ans;
    }
    
    /** Get the front element. */
    int peek() {
        while(!s1.empty()){
            s2.push(s1.top());
            s1.pop();
        }
        return s2.top();
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return s1.empty()&&s2.empty();
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

另一种写法:

class MyQueue {
public:
    /** Initialize your data structure here. */
    //s1记录队列的压入顺序,s2作转换使用;因此s2和s1是逆序的
    stack<int> s1,s2;
    MyQueue() {

    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
        s1.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        if(s2.empty()){//说明s2没有被操作过,操作一遍
            while(!s1.empty()){
                s2.push(s1.top());
                s1.pop();
            }
        }
        int ans = s2.top();
        s2.pop();
        return ans;
    }
    
    /** Get the front element. */
    int peek() {
        if(s2.empty()){
            while(!s1.empty()){
                s2.push(s1.top());
                s1.pop();
            }   
        }
        return s2.top();
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return s1.empty()&&s2.empty();
    }
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue* obj = new MyQueue();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->peek();
 * bool param_4 = obj->empty();
 */

LeetCode682.棒球比赛

典型的栈,会逆波兰算法,这个很快就会有思路

class Solution {
public:
    int calPoints(vector<string>& ops) {
        stack<int> s;
        for(int i=0;i<ops.size();i++){
            if(ops[i]=="+"){
                int a = s.top();
                s.pop();
                int b = s.top();
                s.push(a);
                s.push(a+b);
            }else if(ops[i]=="C"){
                s.pop();
            }else if(ops[i]=="D"){
                int c = s.top();
                s.push(2*c);
            }else{
                //牢记将string转换成int的方法!
                s.push(stoi(ops[i]));
            }
        }
        int ans = 0;
        while(!s.empty()){
            ans+=s.top();
            s.pop();
        }
        return ans;
    }
};

LeetCode496.下一个更大的元素I

感觉不用用栈就可以做啊

官方题解用单调栈+hashmap,有点小题大做了

class Solution {
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
        vector<int> v;
        for(int i=0;i<nums1.size();i++){
            bool flag = true;
            for(int j = 0;j<nums2.size();j++)
                if(nums2[j]==nums1[i])
                    for(int k = j+1;k<nums2.size();k++)
                        if(nums2[k]>nums1[i]){
                            v.push_back(nums2[k]);
                            flag = false;
                            break;
                        }
            if(flag)
                v.push_back(-1);
        }
        return v;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沉迷单车的追风少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值