删除无效的括号问题

261 阅读1分钟

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

给你一个由若干括号和字母组成的字符串 s ,删除最小数量的无效括号,使得输入的字符串有效。

返回所有可能的结果。答案可以按 任意顺序 返回。

Leecode

一、分析

收集不同字面值

两种做法:

  • 不剪枝,收集所有可能性,最后过滤(去重)

  • 剪枝,不过滤(效率高)

怎么剪枝的能力

定义函数f(i,j):从左到右只考虑右括号,i(检查的位置),j(删除的位置)

遇到左括号,i++,遇到右括号,i--,当右括号多时,就需要删了(j)

count = 0,如果count没有变成零以下,说明括号都能匹配

删除无效的括号.png

经历一个for循环,一个计数失效的也没有,说明任何一个前缀右括号都不比左括号多,左括号比右括号多,此时逆序删除左括号(右括号++,左括号--)

二、实现

    // modifyIndex <= checkIndex
    // 只查s[checkIndex....]的部分,因为之前的一定已经调整对了
    // 但是之前的部分是怎么调整对的,调整到了哪?就是modifyIndex
    // 比如:
    // ( ( ) ( ) ) ) ...
    // 0 1 2 3 4 5 6
    // 一开始当然checkIndex = 0,modifyIndex = 0
    // 当查到6的时候,发现不对了,
    // 然后可以去掉2位置、4位置的 ),都可以
    // 如果去掉2位置的 ), 那么下一步就是
    // ( ( ( ) ) ) ...
    // 0 1 2 3 4 5 6
    // checkIndex = 6 ,modifyIndex = 2
    // 如果去掉4位置的 ), 那么下一步就是
    // ( ( ) ( ) ) ...
    // 0 1 2 3 4 5 6
    // checkIndex = 6 ,modifyIndex = 4
    // 也就是说,
    // checkIndex和modifyIndex,分别表示查的开始 和 调的开始,之前的都不用管了  par  (  )
    public static void remove(String s, List<String> ans, int checkIndex, int deleteIndex, char[] par) {
        for (int count = 0, i = checkIndex; i < s.length(); i++) {
            if (s.charAt(i) == par[0]) {
                count++;
            }
            if (s.charAt(i) == par[1]) {
                count--;
            }
            // i check计数<0的第一个位置
            if (count < 0) {
                for (int j = deleteIndex; j <= i; ++j) {
                    // 比如
                    if (s.charAt(j) == par[1] && (j == deleteIndex || s.charAt(j - 1) != par[1])) {
                        remove(
                                s.substring(0, j) + s.substring(j + 1, s.length()),
                                ans, i, j, par);
                    }
                }
                return;
            }
        }
        String reversed = new StringBuilder(s).reverse().toString();
        if (par[0] == '(') {
            remove(reversed, ans, 0, 0, new char[] { ')', '(' });
        } else {// 右括号和左括号都删完了,可以收集答案了
            ans.add(reversed);
        }
    }

三、总结

过滤

剪枝