【发布时间】:2019-04-05 13:15:52
【问题描述】:
我对此感到非常困惑。该代码是生成给定整数列表的所有排列。一旦你这样做了,他们会添加另一个约束,即给定的输入可以有重复,我们只需要唯一的排列。
我的代码有效...我只是对我注意到的一些事情感到惊讶。在查看了代码之后,我质疑我所拥有的特定条件是否是必要的,所以我否定它,看看会发生什么。该代码在 100 个测试用例中仍然可以正常工作。本质上,无论此条件是true 还是false,此代码都有效。
很自然,我想我可以删除条件,因为它似乎没有必要。长话短说......代码现在返回一个空的结果集。我希望比我更聪明的人能解释一下这是怎么可能的,因为我现在怀疑我是否属于这个行业。
有问题的代码行是:
if(seen[i] || (i > 0 && nums[i] == nums[i - 1] && !seen[i - 1]))
特别是!seen[i - 1] 如果您按原样运行此代码,它可以工作。如果您删除否定并将其作为seen[i - 1] 运行,它仍然有效。如果您完全删除 !seen[i - 1] 使得条件看起来像:
if(seen[i] || (i > 0 && nums[i] == nums[i - 1])) 然后代码返回空结果集。我完全糊涂了。
我使用[1,1,2] 作为方法的输入,我的预期结果集是:[[1,1,2],[1,2,1],[2,1,1]]
class PermutationGenerator {
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
if(nums == null || nums.length == 0){
return result;
}
Arrays.sort(nums);
backtrack(nums, new ArrayList<>(), new boolean[100]);
return result;
}
private void backtrack(int[] nums, List<Integer> permutation, boolean[] seen){
if(permutation.size() == nums.length){
result.add(new ArrayList<>(permutation));
return;
}
for(int i = 0; i < nums.length; i++){
if(seen[i] || (i > 0 && nums[i] == nums[i - 1] && !seen[i - 1])){
continue;
}
seen[i] = true;
permutation.add(nums[i]);
backtrack(nums, permutation, seen);
seen[i] = false;
permutation.remove(permutation.size() - 1);
}
}
}
我的问题很简单,这怎么可能?无论是真还是假,代码都可以工作,但完全删除它是行不通的。
【问题讨论】:
-
实际上,我不知道它是如何工作的,因为你在第一次迭代时尝试
seen[i - 1]时有java.lang.IndexOutOfBoundsException -
@Dred 条件也有
i > 0,所以不确定你是如何越界异常的。 -
@Patrick 是的,我已经尝试了很多不同的这种有条件的安排。删除
||会产生重复排列,这是我们想要避免的,因此仅将条件设置为seen[i]是不够的。此外,如果是这种情况,则在删除有问题的部分时代码仍然可以工作,因为条件的第一部分优先。如果seen[i]足够,则代码的其他部分将永远不会被执行。 -
是的,我删除了评论,因为我误读了这个问题,我不确定是什么原因导致它给出了相同的否定结果。可能需要使用调试器单步执行它并查看 i、nums[i] 等的值,以了解此条件在做什么
-
我建议在纸上写出并逐步完成程序,或者使用调试器。否定似乎在做同样的事情,但它会改变是否在递归调用或我相信的 for 循环中找到重复项。无论哪种方式都有效,但绝对需要条件。
标签: java algorithm permutation