思路
46题主要是用递归的方法,从左到右遍历数组,依此将该下标和后面的数字两两交换,然后继续递归下去,并用一个变量start记录当前下标。直到start越过数组下标(nums.length())时结束。
47题主要是比46题要多一个判断重复的处理,47题的代码中比46题的只多了几行,比如对2,2,1,1,要确保第一个元素2只和1个2交换,只和1个1交换(注意它和它自己交换也算一次交换)
(参考:https://blog.youkuaiyun.com/chenchaofuck1/article/details/51194976
https://blog.youkuaiyun.com/mebiuw/article/details/51184815 )
代码如下:
46题
//46 领先98%以上
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
res.clear();
dfs(nums, 0);//
return res;
}
public void dfs(int[] n, int start) {//start表示要被替换元素的位置
if( start >= n.length) {
List<Integer> list = new ArrayList<Integer>();
for(int i : n) {
list.add(i);
}
res.add(list);
return;
}
for(int i = start; i< n.length; i++) {//i从start开始,如果从start+1开始的话,会把当前序列遗漏掉直接保存了下一个序列
int temp= n[i];
n[i] = n[start];
n[start] = temp;
dfs(n, start + 1);//递归下一个位置
//回到上一个状态
n[start] = n[i];
n[i] = temp;
}
}
47题
//47题 领先43%
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
res.clear();
dfs2(nums, 0);//
return res;
}
public void dfs2(int[] n, int start) {//start表示要被替换元素的位置
if( start == n.length) {
List<Integer> list = new ArrayList<Integer>();
for(int i=0; i<n.length;i++) {
list.add(n[i]);
}
res.add(list);//有重复元素时
//可以利用下面这种方式去重,但是速度很慢
// if( !res.contains(list)) {
// res.add(list);
// }
return;
}
//如果后面有重复的元素,要确保只和最多1个1交换,最多只和1个2交换,......
Set<Integer> set = new HashSet<Integer>();
for(int i = start; i< n.length; i++) {//i从start开始,如果从start+1开始的话,会把当前序列遗漏掉直接保存了下一个序列
if(set.contains(n[i])) {
continue;
}
set.add(n[i]);//如果不包含的话,设置访问过
int temp= n[i];
n[i] = n[start];
n[start] = temp;
dfs2(n, start + 1);//递归下一个位置
//回到上一个状态
n[start] = n[i];
n[i] = temp;
}
}