何时在递归中使用ArrayList over array

时间:2010-10-07 13:47:06

标签: java arrays recursion arraylist

所以我有这个问题。我试图编写一个程序来打印所有有效的括号排列,即3个括号,我们可以有((())),(()()),()()(),(())()等

我有一个工作代码

public static void main(String[] args) {
    int number = 3; // No. of brackets
    int cn = number;
    int on = number;
    // open and closed brackets respectively
    char[] sol = new char[6];
    printSol(on, cn, sol, 0);
}

public static void printSol(int cn, int on, char[] sol, int k) {
    if (on == 0 && cn == 0) {
        System.out.println("");
        for (int i = 0; i < 6; i++) {
            System.out.print(sol[i]);
        }
    }

    else {
        if (on > 0) {
            if (cn > 0) {
                sol[k] = '(';
                printSol(on - 1, cn, sol, k + 1);
            }
        }

        if (cn > on) {
            sol[k] = ')';
            printSol(on, cn - 1, sol, k + 1);
        }
    }
}

现在的问题是我想使用ArrayList而不是使用char数组。 我试过但是我遇到了错误。如果有人有任何建议,请告诉我。提出这个问题的主要目的是我想知道在递归问题中我何时更喜欢ArrayLists而不是数组。

P.S。 我很抱歉由于冲浪限制我不得不键入整个程序,并且也可能是一些语法错误,但我尽力了。 谢谢 莫希特

3 个答案:

答案 0 :(得分:2)

我认为你使用char[]做得很好。这很快就达到了目的。

我会说你在实践中遇到的大多数递归问题都不遵循这种模式。这是因为通常需要递归的问题,您在搜索树上搜索一个特定的目标(树上的一个特定叶节点)。您正在执行迭代:您正在尝试访问树上的每个叶节点,并为每个叶节点执行操作。

使用常见的搜索算法(如深度优先搜索),您无需在递归时准备结果,而是在找到目标后放松。

但是对于你这样做的情况,char[]效果很好。您基本上是通过参数solk模拟堆栈(sol保存数据,而k指向堆栈顶部)。正如其他人注意到的那样,您可以直接使用堆栈(通过传递Deque<Character>实现,通常是LinkedList)。

在我看来ArrayList是向后退一步。如果您要使用集合,请使用针对该问题的集合。

编辑:以下是使用Deque的未经测试的实现:

public static void printSol(int cn, int on, Deque<Character> sol) {
    if (on == 0 && cn == 0) {
        System.out.println("");
        for ( Iterator<Character> it = sol.descendingIterator(); it.hasNext(); ) {
            System.out.println(it.next());
        }
    }

    else {
        if (on > 0) {
            if (cn > 0) {
                sol.push('(');
                printSol(on - 1, cn, sol);
                sol.pop();
            }
        }

        if (cn > on) {
            sol.push(')');
            printSol(on, cn - 1, sol);
            sol.pop();
        }
    }
}

//...
printSol(3, 3, new ArrayDeque<Character>(6));

正如您所看到的,很少有变化。

编辑2:我们根本没有讨论过这个具体问题的一件事是StringBuilder

StringBuilder是一种可变的String类型,允许您轻松追加和删除字符。对于这个问题,这也是一个很好的解决方案:

public static void printSol(int cn, int on, StringBuilder sol) {
    if (on == 0 && cn == 0) {
        System.out.println(sol);
    }

    else {
        if (on > 0) {
            if (cn > 0) {
                sol.append('(');
                printSol(on - 1, cn, sol);
                sol.deleteCharAt(sol.length()-1);
            }
        }

        if (cn > on) {
            sol.append(')');
            printSol(on, cn - 1, sol);
            sol.deleteCharAt(sol.length()-1);
        }
    }
}

答案 1 :(得分:1)

您希望避免在递归时按值传递大型数据结构,因为它会占用大量内存。总的来说,这是我唯一能想到的。传递对数组或ArrayList的引用是可以的。我更喜欢ArrayList。

特别针对此问题查看Java的Stack类。

答案 2 :(得分:0)

我意识到没有人(包括我自己)真的回答了你的问题。我认为你已经确信使用ArrayList在这里是不可取的。但是你怎么能让它发挥作用呢?

最简单的方法是基本上用它伪造一个堆栈:

public static void printSol(int cn, int on, ArrayList<Character> sol) {
   //...
   sol.add('(');
   printSol(on - 1, cn, sol);
   sol.remove(sol.size() - 1);