在使用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代码。但是,我的观点是说明传递对象的问题。
答案 0 :(得分:1)
如果答案存在于如此通用的问题(并理解一般性的基本原理),则为persistent data structures。这些是用于在Haskell等语言中进行高效计算的地方,其中所有内容都是不可变的,并且所有算法都基于递归,因此它们当然适合您的情况。也就是说,Java并未针对此类操作进行优化,因此您可能会发现 sound clumsier的解决方案在实践中编写和/或执行的速度更快。
答案 1 :(得分:1)
如果您需要以前的List或Array,那么您可以复制一次,然后递归修改复制的版本,但不需要在每个递归步骤中复制它。