我正在练习Leetcode的采访,其中一个问题是:
给定一组数字,您需要生成所有可能的排列。为了更好地理解,我转向解决方案,其中一个是这样的:
public class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
// Arrays.sort(nums); // not necessary
backtrack(list, new ArrayList<>(), nums);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
if(tempList.size() == nums.length){
list.add(new ArrayList<>(tempList));
} else{
for(int i = 0; i < nums.length; i++){
if(tempList.contains(nums[i]))
continue;
System.out.println("Adding: "+nums[i]);
tempList.add(nums[i]);
backtrack(list, tempList, nums);
System.out.println("Removing: "+nums[i]);
tempList.remove(tempList.size() - 1);
}
}
}
}
这两个print
语句向我展示了如何添加和删除数字(以及因此生成的排列):
添加:1
添加:2
添加:3
删除:3
删除:2
--------&GT;为什么1
这里没有删除? 添加:3
添加:2
删除:2
删除:3
删除:1
添加:2
添加:1
添加:3
删除:3
删除:1
添加:3
添加:1
删除:1
删除:3
删除:2
添加:3
添加:1
添加:2
删除:2
删除:1
添加:2
添加:1
删除:1
删除:2
删除:3
虽然我理解 是如何添加和删除数字,但我不确定为什么它正在以这种方式工作。根据我的理解,在生成第一个排列<1,2,3>
之后,应删除所有这三个数字。但事实并非如此。仅移除<2,3>
,将1
置之后。为什么会这样?我将不胜感激任何帮助。
答案 0 :(得分:1)
你的逻辑似乎有问题,因为在列表中添加1,2,3并且你只是按递归回溯两次所以1总是你的列表的一部分。
In Backtracking,
1
1->2
1->2->3
Remove 3 as no further element
Remove 2 from temp list but after this permute 2,3 ->3,2
There is no need to remove all elements in single iteration over all elements,
you can try with 4 input [1,2,3,4], will be more clear as many permutations will be
there after removal of 2 as 2->3->4, 2->4->3.
请在下面找到替代解决方案
public static void permutate() {
int[] nums = new int[] { 1, 2, 3 };
backTrack(nums, 0, nums.length - 1);
}
public static void backTrack(int[] str, int l, int r) {
if (l == r) {
System.out.print("\n");
for (int ele : str) {
System.out.print(ele);
}
} else {
for (int i = l; i <= r; i++) {
str = swap(str, l, i);
backTrack(str, l + 1, r);
str = swap(str, l, i);
}
}
}
public static int[] swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
return a;
}
如果需要,您可以收集所有排列集合以供进一步使用。
答案 1 :(得分:0)
正常处理 - 添加下一个数字,直到达到限制为止。
添加:1
添加:2
添加:3
我们达到上限,记录1,2,3
烫发和回溯,删除3
删除:3
我们退出backtrack(3)
来电,正如我们刚刚添加2
一样,我们立即将其删除。
删除:2
我们现在继续在第二个位置添加2
并尝试3
的循环。
添加:3
该列表现在包含1,3
。
我们现在循环第三个条目,发现2
尚未出现在列表中。
添加:2
它会将1,3,2
添加到结果列表中。
平衡删除2
。
删除:2
等
答案 2 :(得分:0)
好吧,我会试着解释一下这个
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
if(tempList.size() == nums.length){
list.add(new ArrayList<>(tempList));
} else{
for(int i = 0; i < nums.length; i++){
if(tempList.contains(nums[i]))
continue;
System.out.println("Adding: "+nums[i]);
tempList.add(nums[i]);
backtrack(list, tempList, nums);
System.out.println("Removing: "+nums[i]);
tempList.remove(tempList.size() - 1);
}
}
}
你开始你的backTracking,每个标签都有不同的递归级别,每个级别都有你自己的局部变量(在这种情况下是'i')
backtracking([empty list],[],[1,2,3])
start for i = 0
add to temp list nums[0] = 1
call backtracking
backtracking([],[1],[1,2,3])
start for i = 0 // the other for it's waiting
if(tempList.contains(nums[i])) //its true, then not add nums[0]
now for i = 1
add to temp list nums[1] = 2
call backtracking
backtracking([],[1,2],[1,2,3])
start for i = 0 // the other two 'for' waiting
if(tempList.contains(nums[i]))// true for nums[0],nums[1]
now for i = 2
add to temp list nums[2] = 3
call backtracking
backtracking([],[1,2,3],[1,2,3])
if(tempList.size() == nums.length)//it's true
//we have one permutation [1,2,3]
//add templist in list
finish this level of recursion, return to last level
now for i = 3 then end recursion and remove
tempList.remove(tempList.size() - 1);//after this templist = [1,2]
now here the important part!!
here remove again
tempList.remove(tempList.size() - 1); // after this templist = [1]
now i = 2 //see in this level before i = 1
then the for continue
add to temp list nums[2] = 3
tempList = [1,3]//see that you first add 3 before delete 1
call backtracking
backtracking([],[1,3],[1,2,3])
repeat process...
here only we can add nums[1]
add to temp list nums[1] = 2
tempList = [1,3,2]
call backtracking
backtracking([],[1,3,2],[1,2,3])
if(tempList.size() == nums.length)//it's true
//we have other permutation [1,3,2]
finish this level of recursion, return to last level
i = 3 then end and delete '2' number
i = 3 then end and delete '3' number
now i = 2 // see this is the first recursion and templist = []
add to temp list nums[1] = 2
call backtracking
backtracking([],[2,],[1,2,3]) // and you can continues the recursion.
我建议在netbeans或eclipse中使用debug,你可以看到每个级别的递归,看看它是如何工作的。