在Java中使用对象进行递归的有效方法?

时间:2018-02-03 01:15:51

标签: java recursion

在使用Java的动态编程中,我经常希望在递归步骤中将数组或对象作为参数传递。但是,为了使原始值不被修改,我必须在将对象作为参数传递之前克隆该对象;通过这样做,我将有一个非常不利的时间和空间复杂性,因为该方法可能有数千个堆栈。我从Is there a more efficient way passing object parameters in recursion?读到,可以通过在完成计算后撤消该过程来克服此问题。但是,有时这是不可能撤消的(例如,当递归方法从数组中删除元素时)。有没有人有这个问题的解决方案?我在竞争性编程的背景下使用它,有时候自下而上的解决方案太复杂而且不切实际。

一个例子:

public static int method(ArrayList<Integer> list) {
    if(list.size()==1) {
        return list.get(0);
    }
    ArrayList<Integer> clone = new ArrayList<>();
    for(int e:list) {
        clone.add(e);
    }
    clone.remove(clone.size()-1);
    method(clone);            
}

如果我没有克隆它并改为:

public static int method(ArrayList<Integer> list){
    if(list.size()==1) {
        return list.get(0);
    }
    list.remove(list.size()-1);
    method(list);            
}

原始对象将被修改。在这种情况下,显然可以返回数组的第一个元素,而不是创建这个Cuber-stone代码。但是,我的观点是说明传递对象的问题。

2 个答案:

答案 0 :(得分:1)

如果答案存在于如此通用的问题(并理解一般性的基本原理),则为persistent data structures。这些是用于在Haskell等语言中进行高效计算的地方,其中所有内容都是不可变的,并且所有算法都基于递归,因此它们当然适合您的情况。也就是说,Java并未针对此类操作进行优化,因此您可能会发现 sound clumsier的解决方案在实践中编写和/或执行的速度更快。

答案 1 :(得分:1)

如果您需要以前的List或Array,那么您可以复制一次,然后递归修改复制的版本,但不需要在每个递归步骤中复制它。