【问题标题】:Java Recursion Pass by Reference in ArrayListArrayList中的Java递归通过引用传递
【发布时间】:2018-07-01 06:12:42
【问题描述】:

我正在研究一个问题,以找出给定列表中的所有整数组合可以总计为给定数字。

public class SumProblem {

/*
 * Input 2-2-3-7
 * Output 2+2+3 and 7
 */

public static ArrayList<ArrayList<Integer>>  find(ArrayList<Integer> input, int requiredSum) {
    ArrayList<ArrayList<Integer>> result = new ArrayList<>();
    find(result, requiredSum, 0, new ArrayList<>(), 0, input);
    return result;
}

public static void find(ArrayList<ArrayList<Integer>> result , int requiredSum , int currentSum,  ArrayList<Integer> partialResult, int i, ArrayList<Integer> input) {

    if (currentSum == requiredSum ) {
        ArrayList<Integer> temp = new ArrayList<>();
        temp = (ArrayList<Integer>) partialResult.clone();
        result.add(temp);
        return;
    }

    if (i >= input.size()) {
        return;
    }
    find(result, requiredSum, currentSum , partialResult, i +1, input );
    partialResult.add(input.get(i));
    find(result, requiredSum, currentSum + input.get(i) , partialResult, i +1, input );
}

public static void main(String[] args) {

    ArrayList<Integer> input = new ArrayList<>();
    input.add(2);
    input.add(1);
    input.add(3);
    ArrayList<ArrayList<Integer>>  output = find(input, 3);
    System.out.println(output.toString());
}

}

我在下面写了代码。 我面临一个问题。在下面的代码行中,即使我创建新的 ArrayList 对象并将其分配给 partialResult,它也会将我遍历的所有数字相加。

partialResult.add(input.get(i));

有人可以提出解决方案吗?

【问题讨论】:

  • 如果方法中没有任何代码,很难理解你有什么问题,以及你做错了什么甚至有这个问题。 --- 例如“重新开始”是指partialResult.clear()吗? “将partialResult 转换为结果”是否意味着results.add(new ArrayList&lt;&gt;(partialResult))?如果是这样,您的实际问题是什么?如果不是这样,那是什么?
  • @Andreas,我添加了一段示例代码。
  • @Manish 没有足够的代码。显示调用“查找”方法的部分
  • 你的意思是像find (results, new ArrayList&lt;&gt;(), i) 吗?
  • 我在上面添加了完整的代码

标签: java algorithm recursion arraylist


【解决方案1】:

在这个问题的动态编程解决方案中,您有两个递归调用。一个不应该在结果中包含当前值,另一个应该包含。

您需要制作 partialResult 的防御性副本,否则两个递归调用都会引用 same 列表。列表是一个可变对象。如果两个调用都获得了对同一个列表对象的引用,那么当您向它anywhere添加一些东西时,它们都会看到修改后的列表。

制作列表的防御性副本的最简单方法就是编写:

new ArrayList<>(partialResult)

这是该程序的工作版本:

导入 java.util.*;

public class SumProblem {
    public static List<List<Integer>> find(List<Integer> input, int requiredSum) {
        List<List<Integer>> result = new ArrayList<>();
        find(result, requiredSum, 0, new ArrayList<>(), 0, input);
        return result;
    }

    public static void find(List<List<Integer>> result, int requiredSum, int currentSum,
            List<Integer> partialResult, int i, List<Integer> input) {
        if (currentSum == requiredSum) {
            result.add(new ArrayList<>(partialResult)); // add a copy of the list
            return;
        }

        if (i >= input.size()) {
            return;
        }
        // make defensive copies in the recursive calls
        find(result, requiredSum, currentSum, new ArrayList<>(partialResult), i + 1, input);
        partialResult.add(input.get(i));
        find(result, requiredSum, currentSum + input.get(i), new ArrayList<>(partialResult), i + 1, input);
    }

    public static void main(String[] args) {
        List<Integer> input = List.of(2, 8, 2, 3, 4);
        List<List<Integer>> output = find(input, 7);
        System.out.println(output);
    }
}

输出:

[[3, 4], [2, 2, 3]]

我还做了一些其他更改:

  • 使用List&lt;Integer&gt;List&lt;List&lt;Integer&gt;&gt; 作为类型(代码到接口)
  • 使用List.of() 创建输入列表(Java 9 中添加)
  • 不要在传递给 println 的对象上调用 toString() — 这是不需要的

【讨论】:

  • 很棒的大卫。非常感谢 !你摇滚。
猜你喜欢
  • 2011-05-02
  • 2011-12-12
  • 2012-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-02
  • 2019-11-11
相关资源
最近更新 更多