LeetCode 题解 —— 1541. 平衡括号字符串的最少插入次数

题目相关

题目链接

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、(。需要补充两个 ')'(右括号),使得字符串平衡。

同时,通过分析,我们发现可以不需要堆栈进行辅助。基本伪码逻辑如下:

  1. 如果是左括号 '('。将左括号数量加一,同时将下标加一。
  2. 如果是右括号 ')'。先判断左括号数量,如果数量大于零,数量减一即可;如果不大于零,说明需要插入一个左括号。再判断下一个字符是否是右括号,如果是合法字符而且是右括号,说明是平衡,下标加二即可;如果不是,说明需要增加一个右括号,同时下标加一。
  3. 分析结束后,如果左括号数量不为零,说明需要补充对应两倍的右括号(参考样例 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)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值