[LeetCode-678] 有效的括号字符串

393 阅读2分钟

发布于个人公众号,打开微信,搜索MelodyJerry即可

678. 有效的括号字符串

难度中等通过率38.36%
(40,269/104,970)

给定一个只包含三种字符的字符串:*,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:

  1. 任何左括号 ( 必须有相应的右括号 )
  2. 任何右括号 ) 必须有相应的左括号 (
  3. 左括号 ( 必须在对应的右括号之前 )
  4. * 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
  5. 一个空字符串也被视为有效字符串。

示例 1:

输入: "()"
输出: True

示例 2:

输入: "(*)"
输出: True

示例 3:

输入: "(*))"
输出: True

注意:

  1. 字符串大小将在 [1,100] 范围内。

题解分析

这是昨天的每日一题,是 LC 《20. 有效的括号》 的进阶,多了个*的干扰。

LC 《20. 有效的括号》 那题可以使用双栈来解决,这题也是可以的,不过需要有些变化。

首先,再来阅读题目描述,注意这点:

* 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。

根绝这点提示,这么看来,我们应该是要优先匹配左括号,既然如此,双栈的策略可以如下这么做:

  1. 创建双栈leftStackstarStack,分别存储 (* 出现的下标位置;
  2. 遍历字符串s,若当前遍历的字符为 ( ,当前下标入栈leftStack
  3. 若当前遍历的字符为*,当前下标入栈starStack
  4. 若当前遍历的字符为),需要分3种情况:
    1. 优先匹配 (leftStack不空,直接出栈;
    2. leftStack为空,但starStack不为空,直接出栈,此时*充当(使用;
    3. leftStack为空,且starStack也为空,直接返回 false 即可;
  5. 遍历完了字符串s,可能leftStackstarStack中还存留元素:
    1. 尤其是leftStack不空,那么需要*充当)使用;
    2. leftStackstarStack逐一出栈,得到的是原栈顶的元素,分别表示的( 的下标 leftIndex* 的下标 starIndex
    3. 需要去比较leftIndexstarIndex的大小:leftIndex小于starIndex,才能说明 (* 的左边,这时候*充当(使用,才会有匹配意义;
  6. 最后判断leftIndex是否为空,为空则说明全部的 () 都匹配完了,返回true
  7. 其他情况均匹配失败,直接返回false即可。

以上的双栈策略思路清晰,也方便理解,代码也简单复现。

题解代码

678. 有效的括号字符串

class Solution {
    public boolean checkValidString(String s) {
        // 用栈记录对应字符出现的下标位置
        Stack<Integer> leftStack = new Stack<Integer>(); 
        Stack<Integer> starStack = new Stack<Integer>(); 

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(')
                leftStack.push(i);
            else if (c == '*')
                starStack.push(i);
            else if (c == ')') {
                // 优先匹配(
                if (!leftStack.empty())
                    leftStack.pop();
                else if (!starStack.empty())
                    starStack.pop();
                else
                    return false;
            }
        }

        while (!leftStack.empty() && !starStack.empty()) {
            int leftIndex = leftStack.pop();
            int starIndex = starStack.pop();
            // 必须是(在*左边
            if (leftIndex > starIndex)
                return false;
        }

        return leftStack.empty(); 
    }
}