46. 全排列(无重复数字)
这是无重复数字的全排列。
注意递归函数中的循环(循环起始位置)和used[]数组的使用
class Solution {
//dfs和回溯
LinkedList<List<Integer>> res=new LinkedList<>();
LinkedList<Integer> path =new LinkedList<>();
boolean[] used;
int len=0;
public List<List<Integer>> permute(int[] nums) {
len=nums.length;
used=new boolean[len];
dfs(nums);
return res;
}
void dfs(int[] nums){//把没有被访问过的节点加入Path
if(path.size()==len){//显示使用长度记录当前路径长度比访问path.size()要快
res.add(new LinkedList<>(path));
return;
}
for(int i=0;i<len;i++){
if(used[i]==false){
path.add(nums[i]);
used[i]=true;
dfs(nums);
used[i]=false;
path.removeLast();
}
}
}
}
还学习了交换法,不用申请used[]数组。但是看了看,好像空间也没节省多少啊。可能是因为为了转换成List要将int转换成Integer吧...
class Solution {
//交换法
LinkedList<List<Integer>> ans=new LinkedList<>();
Integer[] arr;
public List<List<Integer>> permute(int[] nums) {
arr=new Integer[nums.length];
int k=0;
for(int num:nums){
arr[k]=num;
k++;
}
dfs(0);
return ans;
}
void dfs(int cur){//固定cur位置,cur之后的每个元素都来这个位置。
//用交换实现这个目的。循环遍历cur及其之后的每个元素。实现枚举n种可能
//递归实现,固定cur后,再固定下一个位置,同样的思路,枚举n-1种可能
//数字交换后乱了怎么办,其实具体数在哪个位置不重要,重要的是固定一个数。和数字本身无关
//即使去重操作事先对数组排序,交换后乱了也不重要,重要的是固定一个数
//排序是为了剪枝(提前终止递归)
if(cur==arr.length-1){
ans.add(Arrays.asList(Arrays.copyOf(arr,arr.length)));
return;
}
for(int i=cur;i<arr.length;i++){
swap(cur,i);
dfs(cur+1);//固定cur位置后,再看下一个位置
//恢复。递归退出到这里,以nums[cur]为起点的情况递归完了。要恢复起始状态
swap(cur,i);
}
}
void swap(int pos1,int pos2){
Integer tmp=arr[pos1];
arr[pos1]=arr[pos2];
arr[pos2]=tmp;
}
}

浙公网安备 33010602011771号