欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

递归与回溯1:生成全部有效括号组合

程序员文章站 2022-03-09 13:41:01
...

从现在开始我们一起来梳理递归相关的问题。递归是高阶算法的核心,回溯、dp都是递归的拓展和延伸。

废话少说,递归的问题一般我们不要急着看代码,因为看了也不懂,而应该先分析问题的本质,从小到大逐步归纳出特征,最后再写代码。而计算机调用的时候恰好是从大小到逐步递进的。

先看一个CC150中的题目,实现一种算法,打印n对括号中的全部有效组合,即左右括号正确配对。

示例:输入n=3,输出:((())), (()()), (())(), ()(()),()()()所以有3个。

这个题如果用递归的话怎么做呢?

如果直接想是不好想的,我们画一个图看一下:

递归与回溯1:生成全部有效括号组合

很明显看到, 从n=2开始就是将上面一层的每一个都是在其左边、右边和包起来三种操作,n从1到2就很明显,从n到3就是图中红色标记的地方。后面的每一层都对前面做相同的三个操作。这就是一个从小到大不断递归的过程。

但是这里有个问题,出现重复了怎么办?例如n=2的时候()()()()是一样的。显然这时候只保留一种就足够了,后序递归操作也只处理一个就行了,那如何去重呢?我们想到集合能保证元素唯一,所以我们可以将每层的元素用集合来保存。代码如下:

 public static Set<String> parentThesis(int n) {
        Set<String> s_n = new HashSet<String>();
        if (n == 1) {
            s_n.add("()");
            return s_n;
        }

        Set<String> s_n_1 = parentThesis(n - 1);
        for (String s : s_n_1) {
            s_n.add("()" + s);
            s_n.add(s + "()");
            s_n.add("(" + s + ")");
        }
        return s_n;
    }

     这里虽然有个for循环,但是只是简单的拼接字符串,因此难度不算很大的。