有效的括号字符串

258 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情

一、题目

LeetCode 有效的括号字符串

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

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

输入: "()"
输出: True

示例 2:

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

示例 3:

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

注意:

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

二、题解

就是需要判断括号是否匹配得上,左括号需要对应有一个右括号,右括号也需要对应有一个左括号,同时呢还有一个*字符可以认为是一个左括号或者一个右括号或者空字符串。

方法一

根据一个左括号需要有一个右括号对应匹配的规则来说,可以通过遍历字符串的所有字符记录左括号的数量,即如果是左括号则左括号的数量增加一个;如果是右括号,就需要一个左括号来匹配的,所有左括号的数量就减少一个;如果是*可以表示为左括号或者右括号或者空字符串,所以左括号数量要么增加一个要么减少一个或者就是不变。因为存在*字符这种特殊情况,就需要考虑左括号可能的情况,可以记录下左括号最小数量minNum以及左括号的最大数量maxNum。那么当遍历到左括号的时候,左括号的最小数量minNum和左括号的最大数量maxNum都需要增加一个;当遍历到右括号的时候,左括号的最小数量minNum和左括号的最大数量maxNum都需要减少一个;当遇到*字符的时候,如果把*当成左括号,那么左括号需要增加一个即左括号的最大数量maxNum增加一个,如果把*当成右括号,那么左括号需要减少一个即左括号的最小数量minNum减一个,如果把*当成空字符串,那么就不用变。对此左括号的最小数量minNum和左括号的最大数量maxNum都可能会出现负数的情况,当左括号的最小数量minNum为负数的时候是不合法的,所以需要重置minNum为0;当左括号的最大数量maxNum为负时,再遇到右括号就无法进行匹配了,说明整个字符串就不是合法的。最后遍历结束时如果括号都能匹配的话左括号最小数量minNum应该为0的。

三、代码

方法一 Java代码

class Solution {
    public boolean checkValidString(String s) {
        int minNum = 0;
        int maxNum = 0;
        for (int i = 0; i <  s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                minNum++;
                maxNum++;
            } else if (c == ')') {
                minNum = Math.max(minNum - 1, 0);
                maxNum--;
                if (maxNum < 0) {
                    return false;
                }
            } else if (c == '*') {
                minNum = Math.max(minNum - 1, 0);
                maxNum++;
            }
        }
        return minNum == 0;
    }
}

时间复杂度:O(n),需要遍历一次字符串的所有字符。

空间复杂度:O(1),只需要使用常数的空间。