每日一题 使括号有效的最少添加

135 阅读2分钟

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

[921] 使括号有效的最少添加

原题链接:

921. 使括号有效的最少添加

示例 1:

输入: s = "())"
输出: 1

示例 2:

输入: s = "((("
输出: 3

解题思路

由题,每个左括号必须对应一个右括号,而且左括号必须在对应的右括号之前。我们可以用计数法来保存左括号和右括号的出现次数,最终得出使括号有效的最少添加的值:
我们可以从左到右遍历字符串,在遍历过程中维护左、右括号的个数以及匹配成功的次数。
如果遇到左括号,则将左括号的个数加 1。
如果遇到右括号,则需要和前面的左括号进行匹配,具体做法如下:

  • 左括号和右括号匹配,对应的计数指示器做加减,然后做之后的匹配
    • 如果当前s[i] === '('(左括号),左括号计数器 left+1
    • 如果当前s[i] === ')'(右括号),则需要:
      • left > 0, 那么右括号就有一个可以与其匹配上,就是合法字符串,所以我们就可以将左括号的个数减 1 (表示牵手成功)
      • left == 0, 那就说目前没有左括号可以匹配,那么 右括号单身狗+1 (right+1),需要后来补充
  • 最后答案,就是未匹配上的left和未匹配上的right的相加之和

步骤一 设置 对应计数器

var minAddToMakeValid = function(s) {
  let left = 0 // 未匹配上的左括号
  let right = 0 // 为匹配上的右括号
 }

步骤二 维护左、右括号的个数以及匹配成功的次数

for(let i = 0;  i<s.length; i++) {
    if(s[i] === '('){
      left++
    }else{
      if(left > 0){
        left--
      }else{
        right++
      }
    }
  }

完整代码

var minAddToMakeValid = function(s) {
  let left = 0 // 未匹配上的左括号
  let right = 0 // 为匹配上的右括号
  for(let i = 0;  i<s.length; i++) {
    if(s[i] === '('){
      left++
    }else{
      if(left > 0){
        left--
      }else{
        right++
      }
    }
  }
  return right + left
};

无论是哪种添加的情况,都是在遇到括号无法进行匹配的情况下才进行添加,因此上述做法得到的添加次数是最少的。

src=http___dingyue.ws.126.net_1kNX5UOlvvZhqzVi4eMVTefclpP9NYP6nSIQPkU9McOAq1553651252093compressflag.jpg&refer=http___dingyue.ws.126.jpg