DFS与回溯专题:全排列
题目链接: 46.全排列
题目描述
代码思路
回溯问题中的全排列,相对比组合、子集等问题,其元素可以颠倒顺序,所以在for循环中每层都是从头开始,无需标记更新起始位置
代码纯享版
class Solution {
public List<List<Integer>> list_all = new ArrayList();
public List<Integer> list = new ArrayList();
public int[] res;
public List<List<Integer>> permute(int[] nums) {
res = new int[nums.length];
backtrack(nums);
return list_all;
}
void backtrack(int[] nums){
if(list.size() == nums.length){
list_all.add(new ArrayList(list));
}
for(int i = 0; i < nums.length; i++){
if(res[i] == 1){
continue;
}
list.add(nums[i]);
res[i] = 1;
backtrack(nums);
res[i] = 0;
list.remove(list.size() - 1);
}
}
}
代码逐行解析版
class Solution {
public List<List<Integer>> list_all = new ArrayList();
public List<Integer> list = new ArrayList();
public int[] res;
public List<List<Integer>> permute(int[] nums) {
res = new int[nums.length]; //数组res用来判断对应位置的数是否用过:0为没用,1为用过
backtrack(nums);
return list_all;
}
void backtrack(int[] nums){
if(list.size() == nums.length){ //当列表list的长度与数组nums长度相同时,说明已经完成一次全排列
list_all.add(new ArrayList(list)); //将list添加到list_all
}
for(int i = 0; i < nums.length; i++){
if(res[i] == 1){ //如果该数字已使用过,则直接退出本次循环
continue;
}
list.add(nums[i]); //否则将该数字添加到list列表中
res[i] = 1; //将该数字标记为已使用过
backtrack(nums); //递归到下一个位置的排列
//将列表list的最后一个数字去掉,同时还原标记
res[i] = 0;
list.remove(list.size() - 1);
}
}
}
其他解法
也可以利用list.contains()方法来判断是否被使用,但这种方式会耗费较多时间。所以最好用前面的方法,已空间换时间
class Solution {
public List<List<Integer>> list_all = new ArrayList();
public List<Integer> list = new ArrayList();
public List<List<Integer>> permute(int[] nums) {
backtrack(nums);
return list_all;
}
void backtrack(int[] nums){
if(list.size() == nums.length){
list_all.add(new ArrayList(list));
}
for(int i = 0; i < nums.length; i++){
if(list.contains(nums[i])){
continue;
}
list.add(nums[i]);
backtrack(nums);
list.remove(list.size() - 1);
}
}
}