题目相关
题目链接
LeetCode 中国,https://leetcode-cn.com/problems/minimum-insertions-to-balance-a-parentheses-string/。
Problem Statement
给你一个括号字符串 s ,它只包含字符 '(' 和 ')' 。一个括号字符串被称为平衡的当它满足:
- 任何左括号 '(' 必须对应两个连续的右括号 '))' 。
- 左括号 '(' 必须在对应的连续两个右括号 '))' 之前。
比方说 "())", "())(())))" 和 "(())())))" 都是平衡的, ")()", "()))" 和 "(()))" 都是不平衡的。
你可以在任意位置插入字符 '(' 和 ')' 使字符串平衡。
请你返回让 s 平衡的最少插入次数。
Samples 1
输入:s = "(()))"
输出:1
解释:第二个左括号有与之匹配的两个右括号,但是第一个左括号只有一个右括号。我们需要在字符串结尾额外增加一个 ')' 使字符串变成平衡字符串 "(())))" 。
Samples 2
输入:s = "())"
输出:0
解释:字符串已经平衡了。
Samples 3
输入:s = "))())("
输出:3
解释:添加 '(' 去匹配最开头的 '))' ,然后添加 '))' 去匹配最后一个 '(' 。
Samples 4
输入:s = "(((((("
输出:12
解释:添加 12 个 ')' 得到平衡字符串。
Samples 5
输入:s = ")))))))"
输出:5
解释:在字符串开头添加 4 个 '(' 并在结尾添加 1 个 ')' ,字符串变成平衡字符串 "(((())))))))" 。
Constraints
1 <= s.length <= 10^5
s
只包含'('
和')'
。
题解报告
样例数据分析
样例 1
下标为 0 的字符是 '(',我们压栈。此时堆栈内只有一个左括号。
下标为 1 的字符是 '(',我们压栈。此时堆栈内只有两个左括号。
下标为 2 的字符是 ')',我们弹栈。获得一个 '(',因此我们需要继续判断下一个字符是否是 ')'。好的,下标为 3 的字符是 ‘)'。这样我们找到一个平衡。
下标为 4 的字符是 ')',我们弹栈。获得一个 '(',因此我们需要继续判断下一个字符是否是 ')'。此时,字符串已经结束,因此我们需要补充一个 ')' 使得字符串变平衡。也就是答案为 1。
样例 2
下标为 0 的字符是 '(',我们压栈。此时堆栈内只有一个左括号。
下标为 2 的字符是 ')',我们弹栈。获得一个 '(',因此我们需要继续判断下一个字符是否是 ')'。好的,下标为 3 的字符是 ‘)'。这样我们找到一个平衡。
此时,字符串已经结束,也就是答案为 0。
样例 3
下标为 0 的字符是 ')',我们弹栈。这个时候堆栈是空的,因此,我们需要先补充一个 ')',此时 ans=1。我们需要继续判断下一个字符是否是 ')'。下标为 1 的字符串是 ')'。
下标为 2 的字符是 '(',我们压栈。此时堆栈内只有一个左括号。
标为 3 的字符是 ')',我们弹栈。获得一个 '(',因此我们需要继续判断下一个字符是否是 ')'。好的,下标为 4 的字符是 ‘)'。
下标为 5 的字符是 '(',我们压栈。此时堆栈内只有一个左括号。
此时,字符串已经结束,但是堆栈里还有一个 '(',说明我们需要补充 2 个 ')' 使得字符串平衡。
因此 ans=1+2=3。
样例 4
忽略。因为我们需要分析的模式都已经出现。
样例 5
忽略。因为我们需要分析的模式都已经出现。
题目分析
LeetCode 官方将本题难度定为中等。首先这是一个模拟题。通过上面的数据分析,我们对不同字符的操作如下:
- 读到 '(' 的时候压栈;
- 读到 ')' 的时候弹栈。如果堆栈为空,说明我们需要插入一个 '(';然后再判断下一个字符是否是 ')',如果不是,需要插入一个 ')';如果是继续分析下下一个字符。
通过数据分析,我们发现以下几种模式:
1、())。字符串平衡。
2、()。需要补充一个 ')'(右括号),使得字符串平衡。
3、))。需要补充一个 '('(左括号),使得字符串平衡。
4、(。需要补充两个 ')'(右括号),使得字符串平衡。
同时,通过分析,我们发现可以不需要堆栈进行辅助。基本伪码逻辑如下:
- 如果是左括号 '('。将左括号数量加一,同时将下标加一。
- 如果是右括号 ')'。先判断左括号数量,如果数量大于零,数量减一即可;如果不大于零,说明需要插入一个左括号。再判断下一个字符是否是右括号,如果是合法字符而且是右括号,说明是平衡,下标加二即可;如果不是,说明需要增加一个右括号,同时下标加一。
- 分析结束后,如果左括号数量不为零,说明需要补充对应两倍的右括号(参考样例 4)。
AC 代码
class Solution {
public:
int minInsertions(string s) {
int left=0;//记录左括号个数
int ans=0;//需要插入个数
int idx=0;
int len = s.length();
while (idx<len) {
if ('('==s[idx]) {
//左括号
left++;
idx++;
} else {
//右括号
if (left>0) {
//前面存在左括号
left--;
} else {
//前面不存在左括号
//加上一个左括号
ans++;
}
//下一个字符也是右括号
if (idx<len-1 && ')'==s[idx+1]) {
//
idx += 2;//向右移动两个
} else {
ans++;
idx++;//向右移动一个
}
}
}
//这里 left 只能为零或者整数
ans += left*2;
return ans;
}
};
时间复杂度
O(N)。
空间复杂度
O(1)。