leetcode678有效的括号字符串Valid Parenthesis String

leetcode678有效的括号字符串Valid Parenthesis String


题目描述:

给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则: 任何左括号 ( 必须有相应的右括号 )。 任何右括号 ) 必须有相应的左括号 ( 。 左括号 ( 必须在对应的右括号之前 )。*可以被视为单个右括号 ) ,或单个左括号),或一个空字符串。一个空字符串也被视为有效字符串。

输入:

字符串s

输出:

这个字符串是否符合要求,true和false

思路:

  • 1 使用两个栈,一个记录'(',一个记录''。当遇到左括号和星号时分别入栈,当遇到右括号')'时,如果左括号栈不为空,则说明左括号够用,出栈一个;如果左括号栈为空,则说明左括号不够用,这时星号应视为左括号,如果星号栈为空,则返回false,如果不为空则出栈一个。最后将所有的右括号遍历完后剩余两个栈。就要判断星号作为右括号是否符合要求。有两种情况,一种是'('是不符合的,一种是'(*'是符合的。所以在存储的时候应该存储他们的下标,每次出站来比较下标,如果星号在前,返回false,如果星号在后,继续遍历到左括号栈为空为止。

代码:

    //方法1,使用两个栈,一个用来存储左括号,一个用来存储星号,当遇到右括号时,如果左括号不为空则弹出左括号,
    //如果左括号栈则说明左括号不够用,再看星号栈是否为空,如果也为空,则说明都不够,返回false。否则弹出星号。
    //当所有的右括号都遍历完后查看左括号和星号栈是否为空,这时候需要比对他们的位置,所以在栈中存储的是左括号和星号所在的位置。
    //如果每次星号的位置在左括号的位置后面说明正确,即“(*”,如果在前面说明是“*(”的情况,说明是错误的,返回false
    public boolean checkValidString1(String s) {
        int left = 0, right = 0, star = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                left++;
            }
            else if (c == ')') {
                right++;
            }
            else if (c == '*') {
                star++;
            }
        }

        if (star < Math.abs(left - right)) {
            System.out.println("false");
            return false;
        }
        Stack<Integer> leftStack = new Stack<>();
        Stack<Integer> starStack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char tmp = s.charAt(i);
            if (tmp == '(') {
                leftStack.push(i);
            }
            else if (tmp == '*') {
                starStack.push(i);
            }
            else if (tmp == ')') {
                if (!leftStack.isEmpty()) {
                    leftStack.pop();
                }
                else if(!starStack.isEmpty()) {
                    starStack.pop();
                }
                else {
                    System.out.println("false");
                    return false;
                }
            }
        }
        while (!leftStack.isEmpty() && !starStack.isEmpty()) {
            if (starStack.pop() < leftStack.pop()) {
                System.out.println("false");
                return false;
            }
        }
        System.out.println(leftStack.isEmpty());
        return leftStack.isEmpty();
    }
  • 2 这个方法就比较牛逼了。使用两个变量,low和high。 low表示左括号比较多,星号视为右括号时左括号的数量。 high表示有括号比较多,星号视为左括号时左括号的数量。 这样在遇到'('时,二者都应该加1,因为都是表示左括号的数量。 在遇到')'时,如果low大于0,说明左括号够,不需要星号作为左括号,则low--.同时high也要减1,因为他也是左括号的数量。 当遇到'*'时,如果low 大于0,说明左括号够,星号应视为有括号,所以low--.而对于high,说明右括号比较多,星号应视为左括号,所以high应该+1. 那么出口在什么地方呢。我们保证low>0.在最后low应该等于0才能返回正确,因为如果low大于0,说明星号作为右括号,如果仍然没有坐括号多说明不符合要求。同时high应该在任何时候都大于0,因为high是将星号视为左括号,如果这时右括号的数量仍然大于左括号和星号总和说明也不符合要求。

代码:

    /*
    思路:使用两个变量lowhigh.
    low代表左括号比较多,星号作为右括号时左括号的数量
    high代表右括号比较多,星号作为左括号时左括号的数量
    那么当遇到'('时,low  high都会增加
    那么当遇到')'时,如果low不为空,说明左括号比较多,则low--.同时因为high也是代表左括号的数量,所以响应的也减high--
    那么当遇到'*'时,如果low不为空,说明左括号比较多,星号作为右括号则low--.同时high是星号作为左括号,所以high++
    出口:high < 0.说明将*当做左括号也不够,返回false
    同时low==0,如果不等于0,说明将星号视为右括号也不够左括号数量。
    这思路真牛逼
     */
    public boolean checkValidString(String s) {
        int low = 0, high = 0;
        for (int i = 0; i < s.length(); i++) {
            char tmp = s.charAt(i);
            if (tmp == '(') {
                low ++;
                high ++;
            }
            else if (tmp == ')') {
                if (low > 0) {
                    low--;
                }
                high--;
            }
            else if (tmp == '*') {
                if (low > 0) {
                    low --;
                }
                high ++;
            }
            if (high < 0) {
                System.out.println(false);
                return false;
            }
        }
        System.out.println(low == 0);
        return low == 0;
    }

zsjwish 

2018年4月26日11:11:24

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值