LC.1190 - 反转每对括号间的子串

721

问题

给出一个字符串 s(仅含有小写英文字母和括号)。

请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。

注意,您的结果中 不应 包含任何括号。

示例 1:

输入:s = "(abcd)"
输出:"dcba"

示例 2:

输入:s = "(u(love)i)"
输出:"iloveu"

示例 3:

输入:s = "(ed(et(oc))el)"
输出:"leetcode"

示例 4:

输入:s = "a(bcdefghijkl(mno)p)q"
输出:"apmnolkjihgfedcbq"

 提示: 

 0 <= s.length <= 2000 
 s 中只有小写英文字母和括号 
 我们确保所有括号都是成对出现的 

思路

好久没写题,一个暴力想了半天,类似反转之类的首先想到的就是栈,暴力的思路就是:

  • 碰到 ( 或字符:入栈
  • 碰到 )或字符:弹栈,直到碰到最临近的栈内的 结束,将拿到的串,顺序再次入栈。这种操作相当于「子字符串反转」并「更新到原串」的效果
import java.util.*;

class Solution {
    public String reverseParentheses(String s) {
        int p = 0;
        int len = s.length();
        if (len == 0) {
            return s;
        }
        Deque<Character> stack = new ArrayDeque<>(len);
        StringBuilder ss = new StringBuilder(len);
        while (p < len) {
            Character c = s.charAt(p);
            if (!c.equals(')')) {
                // pop
                stack.push(c);
            } else {
                // pop and push again
                reverseAndPush(stack);
            }
            p++;
        }
        while (!stack.isEmpty()) {
            ss.append(stack.pop());
        }
        return ss.reverse().toString();
    }

    private void reverseAndPush(Deque<Character> stack) {
        List<Character> list = new ArrayList<>(stack.size());
        while (true) {
            Character c = stack.pop();
            if (c.equals('(')) {
                break;
            }
            list.add(c);
        }
        list.forEach(stack::push);
    }
}

总结

好久没写题,集成插件到 IDE 写,近期有空的话偶尔先恢复一下状态吧...

写这道题的收获是之前一直使用 Stack,今天 SonarLint 提示没必要用,因为它的挺多的压栈弹栈都用重量锁了,于是就换成 Deque 了