代码随想录第11天 20. 有效的括号 +1047. 删除字符串中的所有相邻重复项 +150. 逆波兰表达式求值

LeetCode20. 有效的括号

题目链接:20. 有效的括号

  • 思路:

    • 有效的括号,什么是有效的括号?肯定是成双成对的才行,比如(),[],{} 这 3 种括号各自成双成对。也正因为要成双成对,所以括号的总个数,一定就不能是奇数,这可以排除一种情况。
    • 这题并没有涉及具体的算法思想,只是要按照它的规则去实现就好了。
    • 括号无效的情况有3种。 
      • 第一种情况,字符串里左方向的括号多了 ,所以不匹配。
      • 第二种情况,括号没有多余,但是 括号的类型没有匹配上。
      • 第三种情况,字符串里右方向的括号多了,所以不匹配。
    • 实现思路: 
      • 遍历到左边的符号时,在栈里压入一个其对应的右方向括号。遍历到右方向的括号的不压入。   
      • 为什么呢?
      • 因为在括号有效时,遇到左方向的括号,字符串中肯定会有右方向的括号与其对应,所以在遍历到左方向的括号时压入一个其对应的右方向的括号。如果之后在字符串中遍历到的这个括号是右方向的括号,就取出栈顶处的右方向的括号与当前遍历到的右方向括号 进行比较。比对不上,说明括号无效,比对上了,就继续遍历字符串的下一个字符。
  •  代码:

    class Solution {
    public:
        bool isValid(string s) {
        //长度为奇数,直接排除
        if(s.size() % 2) {return false;}
        
        //正常偶数个
        stack<char>st;
        for(int i = 0; i < s.size(); i++) {
            //遍历到3种左括号时,push其对应的右括号入栈
            if(s[i] == '(' ) {st.push(')');}
            else if (s[i] == '[' ) {st.push(']');}
            else if (s[i] == '{') {st.push('}'); }
    
           // 第三种情况:原字符串中,右括号多。栈中压入的是右方向的括号。如果在遍历过程中栈已经为空了,当前的遍历的右方向的括号 ,说明右方向的括号多了。无效,return false
    
           // 第二种情况:没匹配上。 遍历到字符串中的右方向的括号时,栈顶不是其匹配的,也无效 
            else if (st.empty() || st.top() != s[i]) { return false; }
    
            // 右方向括号比对成功,弹出栈顶的这个右方向括号
             else st.pop(); 
        }
    
        // 第一种情况:字符串中左方向括号多,这种情况是遍历完了字符串,但是栈不为空。又因为遍历到一个左方向括号就压入一个右方向括号,遍历完,栈不为空,就是左方向括号多了,无效return false,如果遍历完,栈空的,说明有效都匹配了return true
            return st.empty();
        }
        
    };

  • 时间复杂度: O(n)

    • 一层for循环的遍历。
  • 总结:

     括号匹配的,只在遍历到左方向的括号时,才压入其对应的右方向括号。遍历到有方向的括号,不压入,而是取出栈顶的右方向括号进行比较。这个思路确实新奇也有效。

视频链接

文章链接


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

题目链接:1047. 删除字符串中的所有相邻重复项

这也是一道栈的经典题目。

  • 思路:

    • 给我们一条字符串,然后我们要删除相邻相同的元素,删除此次相邻相同元素后,如果又有新的相邻相同元素就接着删除。直到没有相邻相同元素为止。
    • 因为我们想要删除相邻重复项的时候,那我们是不是要在遍历这一项的时候,还要知道上一项是什么,并跟它比较。考虑的这个思路,我们可以用到 栈 来完成。
    • 栈的目的,就是存放我们遍历过的元素。遍历当前元素时,去栈里看一下栈顶这个元素是不是相同元素,是的话把这个元素pop掉,不是的话,把这个元素放进栈里。
    • 最终字符串的元素遍历结束后,从栈里pop出来的元素是倒序的,反转一下,就得到了我们想要的结果。
    • 考虑到用 栈 存放之后,还要考虑弹出,反转,有些繁琐,也可以试试 用 字符串来模拟 栈的操作。 用字符串的尾部进入, 有元素要进入就push_back() 从尾部进入,有相邻相同元素要弹出就pop_back(),最终返回这个字符串就好了。
  • 代码:

    class Solution {
    public:
        string removeDuplicates(string s) {
         string result;
          for(int i = 0 ; i < s.size(); i++) {
              //刚开始时,result为空,要放进去;之后的比对不上也要放进去 
              if(result.empty() || s[i] != result.back()) {result.push_back(s[i]);}
              //比对成功,是相邻相同元素,就弹出
              else {result.pop_back();}
                }
           return result;     
        }
    };
  • 时间复杂度: O(n)

    • 一层for循环,自然是O(n)
  • 总结:  这题有点“消消乐”的感觉。用 栈 的思想最合适了。栈就适合处理 符号匹配,消消乐的问题。

视频链接

文章链接


LeetCode150. 逆波兰表达式求值

题目链接:150. 逆波兰表达式求值

  • 思路:

    • 题目要求根据 逆波兰表达式  来求表达式的值
    • 什么是逆波兰表达式?
      • 逆波兰表达式是一种后缀表达式,后缀其实就是指运算符写在后面。而我们从小到大用的都是中缀表达式,就是把运算符写中间。例如 1 + 2  ,8 * 9 这些,他们的运算符都在中间。   
    • 这题也是用到 栈 的一道经典题。
    • 做题思路:遇到数字就入栈;遇到运算符就取出栈顶的两个数字进行计算,再将结果压入栈中。
  • 代码:

    class Solution {
    public:
        int evalRPN(vector<string>& tokens) {
        stack<long long> st;
        long long nums1,nums2;
        //遍历字符串token
        for(int i =0; i<tokens.size(); i++) {
            //遇见运算符就取出2个元素进行计算
            if(tokens[i]=="+" || tokens[i]=="-" || tokens[i]=="*" || tokens[i]=="/") {
                //nums1取的是表达式里算符右边的数,nums2取的是左边的
              nums1 = st.top(); st.pop();
              nums2 = st.top(); st.pop();
                 if (tokens[i] == "+") st.push(nums2 + nums1);
                 if (tokens[i] == "-") st.push(nums2 - nums1);
                 if (tokens[i] == "*") st.push(nums2 * nums1);
                 if (tokens[i] == "/") st.push(nums2 / nums1);  
            }
            //否则,遇见数字,把数字压进去
            //stoll函数把字符串转换为long long int 类型的整数
            else{ st.push(stoll(tokens[i]));}
        }
           int result = st.top();
           st.pop();
           return result;
    
        }
    };
  • 时间复杂度:O(n)

  • 总结:

    • 这题也是栈的经典题目。到现在我们已经接触过 使用 栈 来解决的3道题了。它们都有一种消消乐的感觉,比如这题 遇到运算符,就消掉栈顶的2个数字,并压入计算的结果。LeetCode1047. 删除字符串中的所有相邻重复项 是 遇到相邻相同的就消。LeetCode20. 有效的括号  是利用栈 “消掉” 括号。

视频链接

文章链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值