NC43 没有重复项数字的所有排列
描述
给出一组数字,返回该组数字的所有排列
例如:
[1,2,3]的所有排列如下
[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2], [3,2,1].
(以数字在数组中的位置靠前为优先级,按字典序排列输出。)
分析
- 首先对数组排序,这样从左向右便利能保证总是小数在前面。
- 每一次递归就是添加一个数,直到所有的数用尽。用boolean数组标记是否被使用过。
- 每个递归里面有一个循环,遍历未被加入的数,同时标记这个数,并传递到下一层,下层结束后,还需要恢复原状。
- 当递归的次数等于数组长度时,即把生成的排列加入到最终结果集,注意新new一个list,不要覆盖已经加入的list。
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer>> permute(int[] num) {
Arrays.sort(num);
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
boolean[] flag = new boolean[num.length];
backTrack(res,list,0,flag,num);
return res;
}
public void backTrack(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> list, int step, boolean[] flag, int[] num){
if(step == num.length){
res.add(new ArrayList<>(list));//一定要new一个list
return;
}
for(int i = 0; i < num.length; i++){
if(flag[i] == false){
flag[i] = true;
list.add(num[i]);
backTrack(res,list,step+1,flag,num);
flag[i] = false;
list.remove(list.size()-1);
}else{
continue;
}
}
return;
}
}
NC42 有重复项数字的所有排列
描述
一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
分析
与无重复数字的区别在于去重。
当左边的数字和当前数字相同,并且标记为false,说明左面的那个数已经遍历过了,并且被恢复了现场,所以需要跳过当前这个数;若标记为true,说面左面的那个数加入到了list,这不影响当前数加入list,因此加入当前数。
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) {
Arrays.sort(num);
ArrayList<ArrayList<Integer>> res = new ArrayList<>();
ArrayList<Integer> list = new ArrayList<>();
boolean[] flag = new boolean[num.length];
backTrack(res,list,0,flag,num);
return res;
}
public void backTrack(ArrayList<ArrayList<Integer>> res, ArrayList<Integer> list, int step, boolean[] flag, int[] num){
if(step == num.length){
res.add(new ArrayList<>(list));
return;
}
for(int i = 0; i < num.length; i++){
if(i > 0 && num[i-1] == num[i] && flag[i-1] == false){
continue;
}
if(flag[i] == false){
flag[i] = true;
list.add(num[i]);
backTrack(res,list,step+1,flag,num);
flag[i] = false;
list.remove(list.size()-1);
}else{
continue;
}
}
return;
}
}