括号字符串最短长度计算 | 豆包MarsCode AI刷题
这道题考察了我们对栈的运用,以及如何在栈的操作中最小化字符串的长度。题目中的括号字符串只包含 '('
和 ')'
,我们可以通过将相邻的括号对 ()
进行合并操作,从而减小字符串的长度。这道题属于字符串处理和栈操作的综合问题,下面我们来详细分析题意、解题思路以及代码实现的关键点。
题目分析
题目给定了一串只包含 '('
和 ')'
的括号字符串。我们有两种操作选择:
- 将相邻的一对括号
'()'
合并成'('
。 - 将相邻的一对括号
'()'
合并成')'
。
经过若干次操作后,我们希望将字符串缩短到最小长度,并求出最小长度是多少。
解题思路
由于我们可以选择将 '()'
转换成 '('
或 ')'
,这意味着我们可以“消掉”一对括号。如果我们仔细观察,可以发现,对于每一个'()'
,我们可以在缩短过程中将其转换为单个字符,最终目标是让字符串变成最短的可能形式。
关键思路
在这个问题中,栈是一种非常适合的工具,因为栈本身是“后进先出”的结构,能够帮助我们很方便地处理括号的配对关系。
我们可以通过栈的压栈和出栈操作来判断:
- 当前括号是否可以和栈顶元素形成配对并消掉。
- 如果无法消掉,就需要压栈以供后续的括号判断。
操作规则
对于栈的操作,我们主要分两种情况来处理:
-
如果当前字符是
'('
,我们直接将它压入栈中。 -
如果当前字符是
')'
,我们需要判断栈顶的情况:- 如果栈顶元素是
'('
,那么我们找到了一对配对的括号'()'
,可以进行“消除”操作。这里的“消除”指的是将栈顶的'('
出栈,然后将其合并成一个特殊字符'?'
放回栈中,用于标记当前已配对的括号对。 - 如果栈顶元素是
'?'
,说明前面已经合并过一个括号对,我们可以再次弹出栈顶的'?'
,并继续保持当前的平衡。
- 如果栈顶元素是
经过多轮操作后,栈中剩下的字符数即为最终的最短长度。
核心代码解析
以下是完整的代码实现:
public static int solution(String s) {
char[] arr = s.toCharArray();
Stack<Character> st = new Stack<>();
for (char c : arr) {
if (c == '(') {
// 遇到'('直接入栈
st.push(c);
} else {
// 遇到')'时进行配对消除判断
if (!st.isEmpty() && (st.peek() == '(' || st.peek() == '?')) {
st.pop(); // 移除栈顶的'('或'?',表示消除
// 进一步合并,确保只保留一个'?'作为当前的消除标记
while (!st.isEmpty() && (st.peek() == '(' || st.peek() == '?')) {
st.pop();
}
// 将合并后的标记符号'?'重新压栈
st.push('?');
} else {
// 如果无法消除,直接将')'压栈
st.push(c);
}
}
}
return st.size();
}
代码详解
-
初始化和遍历:
- 将字符串
s
转换为字符数组arr
,方便逐个字符处理。 - 初始化一个空栈
st
,用于存储未消除的括号。
- 将字符串
-
入栈操作:
- 遍历字符数组
arr
,当遇到'('
时,直接将其压入栈中。
- 遍历字符数组
-
配对消除:
-
当遇到
')'
时,先检查栈顶元素。- 如果栈顶是
'('
或'?'
,说明当前')'
可以和栈顶配对消除。 - 移除栈顶的
'('
或'?'
后,将')'
变为'?'
标记当前已配对的状态。
- 如果栈顶是
-
通过
while
循环进一步合并多余的?
标记,确保栈中只保留一个'?'
。
-
-
最终结果:
- 遍历完字符串后,栈中的字符数量即为最短长度,因为所有能够消除的括号对都已消除。
栈操作过程示例
假设输入字符串为 "((()))()"
,我们分析其栈的变化过程:
-
初始栈为空。
-
遍历字符串:
'('
入栈 → 栈内容:['(']
'('
入栈 → 栈内容:['(', '(']
'('
入栈 → 栈内容:['(', '(', '(']
')'
遇到栈顶为'('
,弹出 → 栈内容:['(', '(']
')'
遇到栈顶为'('
,弹出 → 栈内容:['(']
')'
遇到栈顶为'('
,弹出 → 栈内容:[]
'('
入栈 → 栈内容:['(']
')'
遇到栈顶为'('
,弹出 → 栈内容:[]
最终栈为空,因此最短长度为 0
,即所有括号对都能完全配对消除。
时间和空间复杂度分析
- 时间复杂度:遍历字符串一次,每个字符进行常数时间操作,因此时间复杂度为
O(n)
。 - 空间复杂度:最坏情况下,栈中存储所有括号,因此空间复杂度为
O(n)
。
边界情况分析
- 空字符串:返回
0
。 - 没有配对的括号:如
"(((("
或"))))"
,返回栈中的字符数量,因为没有配对情况。 - 完全配对的括号:如
"()()"
,最终栈会为空,返回0
。