前端算法小白攻略24-leetcode(删除最外层的括号)

550 阅读4分钟

「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战

前言

今天这个删除最外层的括号着实很省代码料,相比与有效括号字符串,今天我们只需要处理一种类型小括号了,而且不必勉强自己用栈来解题,你会发现思路真的很重要。

题目描述

1021. 删除最外层的括号

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

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

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

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

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/re… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

思路有点啰嗦,可以直接跳看解题,思路你要是能看懂,我真得感谢你

  1. 首先我们需要明确这道题的目标,不要被题目给的定义搞糊涂了,不必在意什么原语啥的,我们先抽离出有效题意
    1)题目让我们处理的是个由只包含小括号的有效括号字符串组成的有效括号字符串连接体,题目中的原语就是每个有效括号字符串子集
    2)我们要做的是把每个有效括号字符串的子集的最外层括号去掉
  2. 我们要做的第一步就是找出每个有效括号字符串子集,第二步就是把有效括号字符串的子集的最外层括号去掉得到,最后再连接起来,你以为我会像这样分三步做吗?
  3. 刚开始我们可能会联想到之前做的有效括号字符串这题,你可能会说,我直接遍历开找有效括号字符串不就行了吗,找到一个就去掉括号存起来,最后再拼接一下,那你想想,我可不可以在遍历的时候就进行拼接呢?而且还可以在遍历的过程中过滤掉我们要删除的有效括号字符串子集的最外层括号,这样是不是一步就得到了结果?
  4. 既然要一步到位,那么怎么做呢?
    之前解析有效括号字符串的时候,我一直在想,这不就是有闭合的思路在吗,正反相加归0,但是它有三种括号不好处理,今天这题只有一种括号,直接+1,-1求和不就行了??
    1)左括号代表+1,右括号代表-1,如果要形成有效括号,那是不是得求和sum为0,但是我们的目的不是求和,而是要过滤拼接最终结果,每次遍历我们要对sum进行加减1操作,sum = 1表示我们至少处理过一个左括号
    2)那么,什么时候我们要拼接左括号呢?当sum代表左括号的个数已经有一个了时我们再拼接(也就是sum>0),是不是就把第一个左括号去掉了
    3) 如果遇到右括号什么时候该拼接呢,首先遇到右括号,我们的sum需要减1,当sum代表我们处理过的左括号至少要有2个才能拼接这个右括号吧(()就是这样的情况,即sum>1
    4)这样的话在第一个有效括号字符串末尾sum=0,sum前一位是1不需要拼拼接的一位,sum再前一位是2,是拼接的一位,下面就继续下个有效括号字符串子集的遍历拼接

开始解题

虽然废话半天,但都是我做题的思路总结,辛苦半天,就几行代码,呵呵了

var removeOuterParentheses = function(s) {
    let res = '';
    let sum = 0;
    for(char of s) {
        // 这里两种情况需要拼接括号,当sum>0代表有至少一个0没消除的左括号标记,这个时候可以继续拼接左括号
        // 当遇到右括号的时候,至少要有两个没消除的左括号标记就是sum>1
        // sum++和sum--可以理解为,遇到左括号sum+1,遇到右括号sum-1
        if((char === '(' && sum++ > 0) || (char === ')' && sum-- > 1)) res += char;
    }
    return res;
};