leetcode:678. 有效的括号字符串

题目来源

题目描述

在这里插入图片描述

题目解析

题目解析

  • 如果没有*:用一个变量,遇到左括号,自增1,遇到右括号,如果此时计数器已经为0了,直接返回false,否则自减1,一旦计数器出现了负数,立即返回false,最后还要看变量是否为0即可
  • 难点是这里有*, 它既可以作为(,又可以作为)。问题是它什么时候当做括号来用呢?举个极端例子:
    • *):此时*作为(
    • )*:此时*当左括号,右括号,还是空,*( 都是不对的
    • 总之:只要*)的前面,就一定可以消除)
  • 算法:
    • 用两个stack,分别存放(*的位置
    • 遍历字符串:
      • 当遇到*时,压入*
      • 当遇到(时,压入(
      • 当遇到)时:
        • 如果leftStack和starStack均为空,返回false
        • 如果leftStack不为空,则pop出一个(来抵消当前),否则从starStack中pop出一个*来当做(来抵消)
  • 遍历结束后,我们希望leftStack中没有多余的(;如果有,我们可以尝试用*来抵消它:
    • 当star和left均不为空时,进行循环:
      • 如果left的栈顶左括号的位置在star的栈顶星号的右边,那么就组成了 *( 模式,直接返回false
      • 否则就说明星号可以抵消左括号,各自pop一个元素。
    • 最终退出循环后我们看left中是否还有多余的左括号,没有就返回true,否则false
class Solution {
public:
    bool checkValidString(string s) {
        std::stack<int> left, star;
        for (int i = 0; i < s.size(); ++i) {
            if(s[i] == '*'){
                star.push(i);
            }else if(s[i] == '('){
                left.push(i);
            }else{
                if(left.empty() && star.empty()){
                    return false;
                }
                if(!left.empty()){
                    left.pop();
                }else{
                    star.pop();
                }
            }
        }
        
        while (!left.empty() && !star.empty()){
            if(left.top() > star.top()){
                return false;
            }
            left.pop();
            star.pop();
        }
        return left.empty();
    }
};

思路

正向把所有星号转成左括号,反向把所有星号转成右括号,统计左括号和右括号的数量,只要有一个小于0,说明不匹配,也就不是一个有效字符串

class Solution {
public:
    bool checkValidString(string s) {
        int left = 0, right = 0, n = s.size();
        for (int i = 0; i < n; ++i) {
            if (s[i] == '(' || s[i] == '*') ++left;
            else --left;
            if (left < 0) return false;
        }
        if (left == 0) return true;
        for (int i = n - 1; i >= 0; --i) {
            if (s[i] == ')' || s[i] == '*') ++right;
            else --right;
            if (right < 0) return false;
        }
        return true;
    }
};

暴力

递归三种情况,分别是当星号为空,左括号,或右括号,只要有一种情况返回true,那么就是true了

class Solution {
public:
    bool checkValidString(string s) {
        return helper(s, 0, 0);
    }
    bool helper(string s, int start, int cnt) {
        if (cnt < 0) return false;
        for (int i = start; i < s.size(); ++i) {
            if (s[i] == '(') {
                ++cnt;
            } else if (s[i] == ')') {
                if (cnt <= 0) return false;
                --cnt;
            } else {
                return helper(s, i + 1, cnt) || helper(s, i + 1, cnt + 1) || helper(s, i + 1, cnt - 1);
            }
        }
        return cnt == 0;
    }
};

类似题目

题目核心思路
leetcode:20. 有效的括号 Valid Parentheses
leetcode:1003. 检查替换后的词是否有效 Check If Word Is Valid After Substitutions
leetcode:678. 有效的括号字符串(包含(或者)和*三种字符)Valid Parenthesis String
leetcode:761. 特殊的二进制序列 Special Binary String
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值