leetcode
leetcode 601 ~ 650
有效的括号字符串

有效的括号字符串

难度:

标签:

题目描述

代码结果

运行时间: 22 ms, 内存: 15.9 MB


/*
 * 题目思路:
 * 使用 Java Stream 实现有效字符串的判断。
 * 我们可以用两个变量来追踪未匹配的左括号数量,
 * 并利用 Stream API 遍历字符,更新计数器的值。
 * 最后判断最低的未匹配左括号数量是否为 0。
 */
import java.util.stream.Stream;
 
public class Solution {
    public boolean checkValidString(String s) {
        int[] counts = new int[2]; // counts[0] 是 minOpen, counts[1] 是 maxOpen
        s.chars().forEach(c -> {
            if (c == '(') {
                counts[0]++;
                counts[1]++;
            } else if (c == ')') {
                counts[0] = Math.max(counts[0] - 1, 0);
                counts[1]--;
            } else { // c == '*'
                counts[0] = Math.max(counts[0] - 1, 0);
                counts[1]++;
            }
        });
        return counts[0] == 0;
    }
}

解释

方法:

这个题解使用两个栈 l 和 sign 分别存储左括号 '(' 和星号 '*' 的下标。遍历字符串,遇到左括号入栈 l,遇到星号入栈 sign,遇到右括号则优先弹出 l 栈顶元素,若 l 为空则弹出 sign 栈顶元素,若 sign 也为空说明没有左括号与当前右括号匹配,返回 false。最后从 l 和 sign 的栈顶开始比较下标,若 l 栈顶元素下标大于 sign 栈顶元素的下标,说明无法匹配,返回 false。若最终 l 栈为空则说明所有的左括号都被匹配,字符串有效,返回 true。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在处理右括号时,优先选择弹出存储左括号的栈`l`而不是星号栈`sign`?
在处理右括号时,优先选择弹出存储左括号的栈`l`是因为左括号与右括号直接匹配是标准的括号匹配规则,这可以直接验证括号的合法性。如果选择用星号来匹配右括号,则实际上是将星号当作左括号使用,这种情况应当是备选方案,在没有左括号可用时才考虑。因此,优先使用左括号栈可以直接、准确地处理大部分标准情况,而星号作为一种灵活的替代品,用于处理特殊或不足的场景。
🦆
如果在遍历结束后,`sign`栈中的星号下标全都小于`l`栈中的左括号下标,这种情况下算法是否还能正确处理,返回正确的结果?
如果在遍历结束后,`sign`栈中的星号下标全都小于`l`栈中的左括号下标,那么这意味着所有的星号都无法作为右括号来匹配这些左括号。因为星号如果作为右括号使用,必须出现在对应左括号的右侧。在这种情况下,剩余的左括号无法找到合适的匹配项,算法将返回`false`,表明字符串不是有效的括号组合。这是算法设计的正确行为,确保了只有当所有的左括号都能被正确匹配时,才认为输入字符串是有效的。
🦆
在最后的栈下标比较过程中,如果`sign`栈为空但`l`栈还有剩余元素,这种情况下的处理逻辑是什么?
如果在最后的栈下标比较过程中,`sign`栈为空但`l`栈还有剩余元素,意味着没有足够的星号可以作为右括号来匹配剩余的左括号。在这种情况下,剩余的左括号无法被匹配,因此算法将返回`false`,表示字符串不是一个有效的括号字符串。这反映了算法确保每一个左括号都必须找到一个对应的右括号或者一个作为右括号的星号才能构成有效的括号匹配。
🦆
算法在处理星号时将其下标直接存入`sign`栈,这是否意味着所有的星号都被默认先当作右括号处理?如果不是,这种处理方式如何确保星号的多重可能性被正确考虑?
算法在处理星号时将其下标存入`sign`栈,并不意味着所有的星号都被默认先当作右括号处理。星号在算法中具有多重可能性:它可以作为左括号、右括号或者什么都不做。存储星号的下标是为了在处理完所有字符后,根据需要动态决定每个星号的角色。在最终的栈下标比较过程中,根据星号和左括号的相对位置,动态决定每个星号是否作为右括号或忽略。这种处理方式灵活地考虑了星号的多重可能性,并确保所有的左括号都能找到合适的匹配项,从而验证字符串的有效性。

相关问题

特殊的二进制序列

特殊的二进制序列是具有以下两个性质的二进制序列:

  • 0 的数量与 1 的数量相等。
  • 二进制序列的每一个前缀码中 1 的数量要大于等于 0 的数量。

给定一个特殊的二进制序列 S,以字符串形式表示。定义一个操作 为首先选择 S 的两个连续且非空的特殊的子串,然后将它们交换。(两个子串为连续的当且仅当第一个子串的最后一个字符恰好为第二个子串的第一个字符的前一个字符。)

在任意次数的操作之后,交换后的字符串按照字典序排列的最大的结果是什么?

示例 1:

输入: S = "11011000"
输出: "11100100"
解释:
将子串 "10" (在S[1]出现) 和 "1100" (在S[3]出现)进行交换。
这是在进行若干次操作后按字典序排列最大的结果。

说明:

  1. S 的长度不超过 50
  2. S 保证为一个满足上述定义的特殊 的二进制序列。