解法一:回溯法
回溯法:一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化抛弃该解,即回溯并且再次尝试。
-
用回溯算法来解决,遍历数组的每一个元素,然后尝试生成所有的排列,当生成一个完整的排列时,记录该排列,并退回到上一步,然后继续生成新的排列。
-
就比如说“123”,我们可以先固定 1,然后递归处理 “23”。把 “123”、“132” 排列完成后,回溯到上一步,固定 2,然后递归处理 “13”,以此类推。
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> temp = new ArrayList<Integer>();
boolean[] used = new boolean[nums.length]; // 是否已经使用
backtrack(nums, used, result, temp);
return result;
}
public void backtrack(int[] nums, boolean[] used, List result, List temp){
if(temp.size()==nums.length){
// 数目达到已经遍历完
result.add(new ArrayList<>(temp)); // 不能写result.add(temp)
return;
}
for(int i=0; i<nums.length; i++){
if(used[i]){
continue;
}
// 没有用过加入temp
temp.add(nums[i]);
used[i] = true;
// 递归
backtrack(nums, used, result, temp);
// 回溯
temp.remove(temp.size()-1); // 不能写temp.remove(nums[i])
used[i]=false;
}
}
}
注意:
- 进入回溯函数时,要先判断
temp
是否已经排列所有元素 temp
加入result
时,要写为result.add(new ArrayList<>(temp))
不能写为result.add(temp)
- 回溯时,
temp.remove(temp.size()-1)
不能写为temp.remove(nums[i])
二刷
temp
加入result
时,要写为result.add(new ArrayList<>(temp))
不能写为result.add(temp)
,否则后续temp更改时,result会跟着更改