代码随想录算法训练营第十一天:栈与队列-20. 有效的括号、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值

day11:栈与队列-20. 有效的括号、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值

LeetCode 20. 有效的括号

题目链接:

20. 有效的括号

文章讲解:

https://programmercarl.com/0020.%E6%9C%89%E6%95%88%E7%9A%84%E6%8B%AC%E5%8F%B7.html

视频讲解:

https://www.bilibili.com/video/BV1AF411w78g

思路和解法:

按照题目描述,只有三种不匹配的情况

1、左括号多余,如([{}](),最左边的(是多余的

2、左右括号类型不匹配,如[{(}}]中间的(}不匹配

3、右括号多余,如[{}]()))),右边多了(

所以用栈模拟下这三种情况就是:

先说三种情况的共性:在遍历字符串时,遇到左括号时,将其对应的右括号放入到栈中,之所以将对应的右括号放入到栈中,是因为之后遍历到右括号时,方便直接与栈顶元素进行匹配,如果符合则可以直接从栈中弹出。

第一种情况:

遍历结束后,如果栈内还有元素,则说明左括号有多的,不符合题目要求

第二种情况:

第一次遍历到右括号时,与栈顶元素不匹配,说明中间有不对应的括号,不符合题目要求

第三种情况:

当还没有遍历完,但是栈已经为空了,说明右括号有多的,不符合题目要求

public class Solution {
    public bool IsValid(string s) {
        //字符串长度为单数的话,肯定不匹配
        if(s.Length % 2 != 0)
            return false;
        Stack<char> stk = new Stack<char>();
        //遍历字符串
        for(int i = 0; i < s.Length; i++)
        {
            //当字符串为左括号时,对应的右括号入栈
            if(s[i] == '(')
                stk.Push(')');
            else if(s[i] == '[')
                stk.Push(']');
            else if(s[i] == '{')
                stk.Push('}');
            //当遍历到的元素(右括号)与栈顶元素(左括号对应的右括号)不匹配时以及右括号多了的情况
            else if(stk.Count == 0 || stk.Pop() != s[i])
                return false;
        }

        //遍历结束后,如果相匹配的话,栈里面应该没有元素
        return stk.Count > 0 ? false : true;
    }
}

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

题目链接:

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

文章讲解:

https://programmercarl.com/1047.%E5%88%A0%E9%99%A4%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E7%9B%B8%E9%82%BB%E9%87%8D%E5%A4%8D%E9%A1%B9.html

视频讲解:

https://www.bilibili.com/video/BV12a411P7mw/

思路和解法:

在删除相邻重复项的时候,其实就是要知道当前遍历的这个元素,我们在前一位是不是遍历过一样数值的元素,利用栈来存放,即遍历当前的这个元素的时候,去栈里看一下之前是不是遍历过相同数值的相邻元素。

public class Solution {
    public string RemoveDuplicates(string s) {
        Stack<char> stk = new Stack<char>();
        foreach(char c in s)
        {
            if(stk.Count > 0 && stk.Peek() == c)
                stk.Pop();
            else
                stk.Push(c);
        }
        //构建字符串
        char[] resultArray = stk.ToArray();
        Array.Reverse(resultArray);
        string result = new string(resultArray);
        return result;
    }
}
StringBuilder
public class Solution {
    public string RemoveDuplicates(string s) {
        //拿字符串直接作为栈,省去了栈还要转为字符串的操作
        StringBuilder res = new StringBuilder();

        foreach(char c in s){
            if(res.Length > 0 && res[res.Length-1] == c){
                res.Remove(res.Length-1, 1);
            }else{
                res.Append(c);
            }
        }
       
        return res.ToString();
    }
}

LeetCode 150. 逆波兰表达式求值

题目链接:

150. 逆波兰表达式求值

文章讲解:

https://programmercarl.com/0150.%E9%80%86%E6%B3%A2%E5%85%B0%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B1%82%E5%80%BC.html

视频讲解:

https://www.bilibili.com/video/BV1kd4y1o7on/

思路和解法:

逆波兰表达式:一种后缀表达式,是一种很方便计算机来做运算的一种表达式。

简单地说,逆波兰表达式相当于是二叉树中的后序遍历,可以把运算符作为中间节点,按照后序遍历的规则画出一个二叉树。

详情查看上面的文章讲解。

模拟过程:

1、遍历这个字符串,遇到数字时则入栈。

2、遍历到操作符时,则取出栈顶的两个数字进行计算

3、计算完毕后,再将数据入栈,继续遍历字符串

public class Solution {
    public int EvalRPN(string[] tokens) {
        int num;
        Stack<int> stk = new Stack<int>();
        foreach(string s in tokens)
        {
            if(int.TryParse(s, out num))
            {
                stk.Push(num);
            }
            else
            {
                int num1 = stk.Pop();
                int num2 = stk.Pop();
                switch(s)
                {
                    case "+":
                        stk.Push(num1 + num2);
                        break;
                    case "-":
                        stk.Push(num2 - num1);
                        break;
                    case "*":
                        stk.Push(num1 * num2);
                        break;
                    case "/":
                        stk.Push(num2 / num1);
                        break;
                    
                }
            }
        }
        return stk.Pop();
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值