【发布时间】:2018-07-14 23:19:43
【问题描述】:
一个经典的回溯示例是生成整数列表的所有(不一定是不同的)排列。
例如,这是我编写的一个函数:
List<List<Integer>> perm_set = new ArrayList<>(); // store permutations
private void permute(int[] nums, List<Integer> perm, boolean[] used) {
if (perm.size() == nums.length) {
// System.out.println(perm);
perm_set.add(new ArrayList<>(perm)); // why is it necessary to add new?
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) {
continue;
}
used[i] = true;
perm.add(nums[i]);
permute_simple(nums, perm, used);
used[i] = false;
perm.remove(perm.size() - 1);
}
}
上述功能有效,但我不明白为什么每次要添加排列时都需要new ArrayList<>(perm),即在每次回溯搜索完成时。我添加了一个打印语句来尝试查看发生了什么,果然排列打印得很好。但是如果我只使用perm_set.add(perm),我最终会得到一个空白列表。
那么,如果每次搜索结束时的当前排列状态是正确的,为什么我必须为每个案例创建一个新副本?
请注意,该示例是任意的。这个问题并不特定于我提供的代码或特定于排列。它更广泛地适用于典型的 DFS 问题。我想了解为什么通常不能简单地直接存储最终结果,以及为什么需要 new 关键字。
谢谢
【问题讨论】:
-
什么是
perm_set?这是发布的代码中唯一一次使用它。另外,nums是什么?这个问题缺乏很多细节和相关背景。 -
是的,它缺少细节,因为示例并不重要。该示例仅用于演示有关回溯的一般概念问题。您询问的所有变量都不会改变或协助基本问题。我在问为什么每次搜索结束时都需要
new关键字。排列示例是任意的,可能是任何其他典型的 DFS 问题。现在由于您不必要的反对,我不太可能得到有助于我了解这种行为的回应。 -
因为如果你只是添加
perm,它仍然可以在外部进行修改。通过创建新列表,您可以确保一旦添加到perm_set数组中,对perm变量的修改不会影响已添加到perm_set的列表 -
所以对
perm的进一步修改仍然会影响列表中的一些perm?那是因为列表是可变的吗?这是有道理的,那么当问题处理例如字符串时,为什么不需要新实例。 -
我不相信代码如图所示会真正起作用。首先,缺少
perm_simple的定义。
标签: java object permutation backtracking