栈与队列探索篇

leetcode20——有效的括号

题目描述:

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

算法思想:

依次扫描字符串遇到左括号入栈,遇到右括号检查栈顶是否为对应的左括号,如果对应弹出栈顶元素,不对应返回false。若最后栈空则返回true。

算法实现:

bool isValid(string s) {
        int slen=s.size();
        //长度为奇数,一定不能匹配成功
        if(slen%2==1) return false;
        stack<char> stack1;
        for(int i=0;i<s.size();i++){
            //左括号入栈
            if(s[i]=='(' || s[i]=='{' || s[i]=='[' ) stack1.push(s[i]);
            //右括号的处理
            else if(s[i]==')'){
                if(stack1.empty() || stack1.top()!='(') return false;
                stack1.pop();
            }
            else if(s[i]=='}'){
                if(stack1.empty() || stack1.top()!='{') return false;
                stack1.pop();
            }
            else if(s[i]==']'){
                if(stack1.empty() || stack1.top()!='[') return false;
                stack1.pop();
            }
        }
        //检查最后栈是否为空
        return stack1.empty();
}

leetcode1047——删除字符串中的所有相邻重复项

题目描述:

给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

算法思想:

初始化一个字符空栈,依次遍历字符串的每个字符,若栈为空直接将字符入栈。若不为空检查当前字符与字符栈顶元素是否相同,若相同弹出栈顶元素且该元素不入栈,若不相同则该元素入栈。最后栈中的元素即为要返回的最终字符的倒叙。

算法实现:

string removeDuplicates(string s) {
        //用字符串代替上述栈,直接得到正序结果
        string res;
        for(char c:s){
            if(res.empty() || c!=res.back()) {
                res.push_back(c);
            }
            else if(c==res.back()) {
                res.pop_back();
            }
        }
        return res;
    }

leetcode150——逆波兰表达式求值

题目描述:

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

示例 1:

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例 2:

输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

算法思想:

初始化一个空的数字栈,依次遍历字符串数组,若不为运算符将该字符串转成int型入栈。若为运算符依次弹出数字栈的两个元素为a、b,并进行相应的运算(b运算符a)并将结果压入栈中,直至遍历完整个字符串数组,最终栈里保存的结果即为所求。

算法实现:

int evalRPN(vector<string>& tokens) {
        stack<int> nums;
        int a,b;
        for(auto s:tokens){
            if(s!="+" && s!="-" && s!="*" && s!="/"){
                nums.push(stoi(s));
            }
            else{
                a=nums.top();
                nums.pop();
                b=nums.top();
                nums.pop();
                if(s=="+") nums.push(b+a);
                else if(s=="-") nums.push(b-a);
                else if(s=="*") nums.push(b*a);
                else nums.push(b/a);
            }
        }
        return nums.top();
    }

leetcode239——滑动窗口最大值

题目描述:

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 

示例 1:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

示例 2:

输入:nums = [1], k = 1
输出:[1]

算法思想:

初始化一个双端队列,队头始终存放窗口的最大值。每遍历下一个窗口时检查要移除的元素(当前窗口的头部)是否为队头元素,若是则队头出队,若不是则不做操作;检查要入队的元素(下一个窗口的尾部)是否比队尾元素大,若大则队尾元素出队直至到小于队尾元素再将该元素入队,若小直接入队。将每次的队头元素分别加入到要返回的数组中即为答案。

算法实现:

    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int>  res;
        deque<int> que;
        for(int i=0;i<k;i++){
            while(!que.empty() && nums[i]>que.back()) que.pop_back();
            que.push_back(nums[i]);
        }
        res.push_back(que[0]);
        for(int i=0;i+k<nums.size();i++){
            if(nums[i]==que[0]) que.pop_front();
            while(!que.empty() && nums[i+k]>que.back()) que.pop_back();
            que.push_back(nums[i+k]);
            res.push_back(que[0]);
        }
        return res;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值