LeetCode 22 括号生成

394 阅读2分钟

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

题目:设计函数输出所有可能且符合括号规则的n对括号排列。

解题思路

因为之前做过一个判断括号是否有效的题目,因此本题的第一反应就是暴力获得所有可能的括号对,之后再遍历判断每个括号的有效性,时间效率不用想就非常低(首先要获得所有可能的括号对,之后进行括号对合法性的判断),方法的话也很简单,通过递归即可,代码可以参考下面的:

public static void getAll(String s, int left, int right, ArrayList result){
        if(left==0&&right==0){
            result.add(s);
            return;
        }
        if(left>0) {
            getAll(s + "(", left - 1, right, result);
        }
        if(right>0) {
            getAll(s + ")", left, right - 1, result);
        }
    }

之后循环遍历list,调用之前判断括号是否合法函数即可。注意上述递归过程,实际上就是遍历一颗完全二叉树,但在遍历二叉树的时候,根据已知条件进行了剪枝,如上述代码的判断左右剩余括号大于0的条件,那有没有一种办法可以对二叉树进一步的剪枝,直接获得我们的正确结果,答案是有的。实际上本题隐藏了一个条件,当左括号剩余数量大于等于右括号的时候,字符串只能加左括号,若左括号小于右括号,那么加左右括号都行(其中左括号需要判断是否大于0,而右括号不需要,这是因为这是在左括号小于右括号的前提下执行的),递归结束得到的就是最终结果,代码如下:

public static List<String> generateParenthesis(int n) {
        ArrayList<String> strings = new ArrayList<>();
        getP("", n, n, strings);
        return strings;
    }

    private static void getP(String s, int left, int right, ArrayList result){
        if(left==0&&right==0){
            result.add(s);
            return;
        }
        if(left<right){
            if(left>0){
                getP(s+"(", left-1, right, result);
            }
            getP(s+")", left, right-1, result); // 函数调用的过程!!!s不变
        }else {
            getP(s+"(", left-1, right, result);
        }
    }

我看题解里面有人问当n等于3的时候,()()()这个情况是怎么产生的,如果可以理解((()))的产生过程,而不理解()()()的话,可能对递归的调用过程不是很理解,上述代码我加了一个注释,其注释那一行执行的是函数调用的过程,这个过程注意s是不变的,可能是误解根据函数调用过程首先判断左括号剩余数大于0就调用(没错),但之后会再次调用s + ")"这个过程,此时的s不变!

时间复杂度和空间复杂度感觉不太好分析。。。