[路飞]_leetcode-1021-删除最外层的括号

150 阅读3分钟

一、题目描述

有效括号字符串为空 """(" + A + ")" 或 A + B ,其中 A 和 B 都是有效的括号字符串,+ 代表字符串的连接。

  • 例如,"""()""(())()" 和 "(()(()))" 都是有效的括号字符串。

如果有效字符串 s 非空,且不存在将其拆分为 s = A + B 的方法,我们称其为原语(primitive) ,其中 A 和 B 都是非空有效括号字符串。

给出一个非空有效字符串 s,考虑将其进行原语化分解,使得:s = P_1 + P_2 + ... + P_k,其中 P_i 是有效括号字符串原语。

对 s 进行原语化分解,删除分解中每个原语字符串的最外层括号,返回 s 。

示例 1:

输入: s = "(()())(())"
输出: "()()()"
解释: 输入字符串为 "(()())(())",原语化分解得到 "(()())" + "(())",
删除每个部分中的最外层括号后得到 "()()" + "()" = "()()()"。
复制代码

示例 2:

输入: s = "(()())(())(()(()))"
输出: "()()()()(())"
解释:
输入字符串为 "(()())(())(()(()))",原语化分解得到 "(()())" + "(())" + "(()(()))",
删除每个部分中的最外层括号后得到 "()()" + "()" + "()(())" = "()()()()(())"。
复制代码

示例 3:

输入: s = "()()"
输出: ""
解释:
输入字符串为 "()()",原语化分解得到 "()" + "()",
删除每个部分中的最外层括号后得到 "" + "" = ""。
复制代码

提示:

  • 1 <= s.length <= 105
  • s[i] 为 '(' 或 ')'
  • s 是一个有效括号字符串

本题就是要我们把输入字符串中所有的最外层括号删除,那想要删除所有的最外层括号,最简单的方法将输入字符串按最外层括号拆分为多个子串放入数组

然后循环数组,将每个子串的最外层括号删除,最后将剩余子串连接即可组成结果字符串

但是这种操作需要进行两次循环,并不是本题的最优解法

我们可以在一次循环输入字符串的过程中,直接拆解出需要的结果字符串

解题思路如下:

  1. 初始化 l = 0 记录左括号数量,r = 0 记录右括号数量,left = 0 记录本次区间开始下标,res = "" 记录结果字符串
  2. 遍历字符串,并更新相关变量。当当前字符为 ( 的时候,l++,反之 r++
  3. l === r 的时候,说明找到了一组最外层括号,此时 left 下标指向左括号下标,当前遍历下标 i 指向右括号下标,截取两下标中间部分字符,即为我们需要的结果字符串的一部分
  4. 重置 l = 0,r = 0,left = i+1,重复以上过程,直到输入字符串遍历完成
  5. 此时 res 中保存的就是求得的结果字符串

整体过程如下:

leetcode-1021-删除最外层括号.gif 代码如下:

var removeOuterParentheses = function(s) {
  // 记录左括号数量
  let l = 0,
  // 记录右括号数量
  r = 0,
  本次区间开始下标
  left = 0,
  // 结果字符串
  res = '';
  // 遍历输入字符串
  for(let i = 0;i<s.length;i++){
    // 更新左右括号数量
    if(s[i]==='(') l++;
    else r++;
    // 当左右括号数量相同,说明此时找到了最外层括号
    if(l===r){
      // 截取当前最外层括号的内部字符串
      res += s.substring(left+1,i);
      // 重置左右括号数量为0
      l = 0;
      r = 0;
      // 更新开始下标为下一个最外层括号的开始下标
      left = i+1;
    }
  }
  // 返回结果字符串
  return res;
};

如有任何问题或建议,欢迎留言讨论!