方法一 回溯法
啊 一看完题目就想到回溯,利⽤递归每次向 temp ⾥添加⼀个数字,数字添加够以后再回来进⾏回溯,再向后添加新的解。
可以理解成⼀层⼀层的添加,每⼀层都是⼀个 for 循环
每调⽤⼀层就进⼊⼀个 for 循环,相当于列出了所有解,然后挑选了我们需要的。其实本质上就是深度优先遍历 DFS。
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
backtrack(res, nums, new ArrayList<>());
return res;
}
public void backtrack(List<List<Integer>> res, int[] nums, List<Integer> temp){
if(temp.size() == nums.length){
res.add(new ArrayList<>(temp));
return;
}else{
for(int i = 0; i < nums.length; i++){
if(temp.contains(nums[i])) continue;
temp.add(nums[i]);
backtrack(res, nums, temp);
temp.remove(temp.size() - 1);
}
}
}
}
方法二 递归
假设有⼀个函数,可以实现题⽬的要求,即产⽣ nums 的所有的组合,并且加⼊到 res 数组中。不过它多了⼀个参数,index,即只指定从 nums [ index ] 开始的数字,前边的数字固定不变。
upset(List<List<Integer>> res, int[] nums, int index)
如果有这样的函数,那么⼀切就都简单了。
如果 index 等于 nums 的⻓度,那么就表示 index 前的数字都不变,也就是全部数字不变,我们只需要把它加到 res 中就⾏了。
如果是其它的情况,只需要⽤⼀个 for 循环,把每⼀个数字都放到 begin ⼀次,然后再变化后边的数字就够了,也就是调⽤ upset 函数,从 index + 1 开始的所有组合。
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
upset(res, nums, 0);
return res;
}
public void upset(List<List<Integer>> res, int[] nums, int index){
if(index == nums.length){
ArrayList<Integer> temp = new ArrayList<Integer>();
for(int i = 0; i < nums.length; i++){
temp.add(nums[i]);
}
res.add(new ArrayList<>(temp));
return;
}
for(int i = index; i < nums.length; i++){
swap(nums, i, index);
upset(res, nums, index + 1);
swap(nums, i, index);
}
}
public void swap(int[] nums, int i, int index){
int temp = nums[i];
nums[i] = nums[index];
nums[index] = temp;
}
}