给出一组可能包含重复项的数字,返回该组数字的所有排列。结果以字典序升序排列。
数据范围:
,数组中的值满足 
要求:空间复杂度
,时间复杂度
import java.util.*; public class Solution { ArrayList<ArrayList<Integer>> list = new ArrayList<>(); // 存最终全排列结果 ArrayList<Integer> tmp = new ArrayList<>(); // 当前排列结果 Set<Integer> set = new HashSet<>(); // 存已用数组元素的下标,防重复 public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) { // write code here Arrays.sort(num); // 升序 dfs(num); // 调用 dfs return list; } // dfs public void dfs(int[] nums) { if (tmp.size() == nums.length) { ArrayList<Integer> t = new ArrayList<>(tmp); if (!list.contains(t)) list.add(t); // 由于元素可能重复,导致排列可能重复,要判断一下 return; } for (int i = 0; i < nums.length; i++) { if (set.contains(i)) continue; // 下标重复 tmp.add(nums[i]); set.add(i); dfs(nums); // 排列数组下个元素 tmp.remove(tmp.size() - 1); // 回溯 set.remove(i); } } }
public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) { ArrayList<ArrayList<Integer>> llst = new ArrayList<>(); ArrayList<Integer> data = new ArrayList<>(num.length); Arrays.sort(num); for(int i=0;i<num.length;i++){ data.add(i,num[i]); } permute(llst,new ArrayList<Integer>(),data); return llst; } public void permute(ArrayList<ArrayList<Integer>> llst,ArrayList<Integer> lst,ArrayList<Integer> data){ if(data.size() == 0) llst.add(lst); HashSet<Integer> set =new HashSet<>(); for(int i=0;i<data.size();i++){ if(set.contains(data.get(i))) continue; set.add(data.get(i)); ArrayList<Integer> t1 = new ArrayList<Integer>(lst); ArrayList<Integer> t2 = new ArrayList<Integer>(data); t1.add(t2.get(i)); t2.remove(i); permute(llst,t1,t2); } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param num int整型一维数组 * @return int整型ArrayList<ArrayList<>> */ public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) { // write code here // 左程云老师讲过全排列的分支限界递归法解决不重复全排列问题 // 调用一个递归函数,这个递归函数负责对当前i位置的数字进行与i ~ num.length - 1中的位置依次互换,然后继续考察i + 1处的情况 // 分支界限法去重:定义一个HashSet,这个位置没有出现过该值才允许进入分支,否则跳过 // 算法的时间复杂度0(N!),额外空间复杂度0(N!) // 用于记录所有路径的结果 ArrayList<ArrayList<Integer>> finalResults = new ArrayList<>(); // 调用这个递归函数,从num数组的0位置开始,将每一次找到的oneResult填进finalResult中 process(num, finalResults, 0); // 给finalResults中的元素按照字典序升序排列 finalResults.sort((o1, o2) -> { // 遍历两个list的每个元素,找到第一对不相同的,按照升序返回 int i = 0, j = 0; while (i < o1.size() && j < o2.size()) { if (o1.get(i) != o2.get(j)) { return o1.get(i) - o2.get(j); } i++; j++; } return 0; }); // 返回最终的答案finalResults return finalResults; } public void process(int[] num, ArrayList<ArrayList<Integer>> finalResults, int i) { // 递归出口(底部) if (i == num.length) { // i越界了,说明整个数组遍历完毕了,将单个路径上的答案oneResult写入总答案finalResults中 // 踩坑点1:这里一定要【现场新创建】一个ArrayList放入答案中,如果提前在主方法创建好,那么随着每次递归的调用,finalResults里面的值也会被修改 ArrayList<Integer> oneResult = new ArrayList<>(); for (Integer n : num) { oneResult.add(n); } finalResults.add(oneResult); } // 递归分支 HashSet<Integer> set = new HashSet<>(); for (int j = i; j < num.length; j++) { if (!set.contains(num[j])) { // 将num[j]登记 set.add(num[j]); // 假设本位置与j位置的元素交换 swap(num, i, j); // 在交换完的基础上继续考察num数组中i+1往后的位置该如何排列 process(num, finalResults, i + 1); // 注意!恢复现场,继续尝试将本位值与num[j + 1]位置的元素交换 // 踩坑点2:一定要【恢复现场】,要不然无法准确列出要分支的情况 swap(num, j, i); } } } // 数组元素交换函数 public void swap(int[] num, int i, int j) { if (i == j) { return; } int t = num[i]; num[i] = num[j]; num[j] = t; } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param num int整型一维数组 * @return int整型ArrayList<ArrayList<>> */ public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { // 为了保证结果的字典升序,先对原始数组排序 Arrays.sort(num); // 定义一个 list 用于记录结果数据 ArrayList<ArrayList<Integer>> encodeRes = new ArrayList<>(); ArrayList<ArrayList<Integer>> deCodeRes = new ArrayList<>(); // 再定义一个 双端队列来存储当前栈帧里面的数,主要用于回溯时增删 Deque<Integer> deque = new LinkedList<>(); HashMap<Integer, Integer> userHashMap = new HashMap<>(); // 定义一个标识,标识是否已经添加过当前元素 boolean[] usedArr = new boolean[num.length]; permuteHelper(encode(num, userHashMap), usedArr, encodeRes, deque); // PriorityQueue // 去重 HashMap<ArrayList<Integer>, Boolean> distinctMap = new HashMap<>(); for (ArrayList<Integer> inList : encodeRes) { ArrayList<Integer> decode = decode(inList, userHashMap); if (distinctMap.get(decode) == null) { deCodeRes.add(decode); distinctMap.put(decode, true); } } return deCodeRes; } // 设计一种编码格式,对可能重复的数据进行不重复编码,最后还原 public static int[] encode(int[] num, Map<Integer, Integer> userHash) { int[] resInt = new int[num.length]; for (int i = 0; i < num.length; i++) { userHash.put(i + 1, num[i]); resInt[i] = i + 1; } return resInt; } public static ArrayList<Integer> decode(ArrayList<Integer> num, Map<Integer, Integer> userHash) { ArrayList<Integer> res = new ArrayList<>(); for (int i = 0; i < num.size(); i++) res.add(i, userHash.get(num.get(i))); return res; } public static void permuteHelper(int[] num, boolean[] usedArr, ArrayList<ArrayList<Integer>> res, Deque<Integer> usedDequeue) { if (usedDequeue.size() == num.length) { // 说明收集满了,开始装配 res.add(new ArrayList<>(usedDequeue)); return; } // 进行递归 for (int index = 0; index < num.length; index++) { if (usedArr[index]) continue; // 元素对应的位置,这样能保证输出时的顺序 usedArr[index] = true; usedDequeue.add(num[index]); permuteHelper(num, usedArr, res, usedDequeue); // 弹栈后,尝试其它的递归,需要先复原状态, 仅保留 res 里面收集的元素 usedArr[index] = false; usedDequeue.removeLast(); } } } 上一份
ArrayList<ArrayList<Integer>> res=new ArrayList<>(); public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) { // write code here Arrays.sort(num); dfs(num ,new boolean[num.length] ,new ArrayList<>()); return res; } public void dfs(int[] num ,boolean[] flag ,ArrayList<Integer> list){ if(list.size()==num.length){ res.add(new ArrayList<Integer>(list)); return; } for(int i=0;i<num.length;i++){ // 跳过重复数据&nbs***bsp;已加入数据 if((i>0 && num[i]==num[i-1] && !flag[i-1]) || flag[i]){ continue; } flag[i]=true; list.add(num[i]); dfs(num ,flag ,list); list.remove(list.size()-1); flag[i]=false; } }
import java.util.*; public class Solution { //声明几个全局的,懒得在迭代方法传值 ArrayList<ArrayList<Integer>> res = new ArrayList<ArrayList<Integer>>(); ArrayList<Integer> arry = new ArrayList<>(); //既然元素有重复的,那么我们就拿索引出来排序,索引肯定不重复 ArrayList<Integer> index = new ArrayList<>(); // 入口方法 public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) { //先按字典序排序 Arrays.sort(num); permute(num); return res; } //迭代方法 void permute(int[] num) { //2.迭代终止条件 if (index.size() == num.length) { res.add(new ArrayList<>(arry)); return; } //3.子部分执行方案 ArrayList<Integer> temp = new ArrayList<>(); //每一层,已经选过的数据 for (int i = 0; i < num.length; i++) { //相同位置,或者值相同都不应该 选取 //(可以用map , key存索引,值存数组的值,但是map最后输出成数组还得再迭代一下,所以这里索引和值还是分开处理吧) if (index.contains(i) || temp.contains(num[i])) continue; temp.add(num[i]); index.add(i); arry.add(num[i]); //1.递归模型 permute(num); //4. 回溯 index.remove(index.size() - 1); arry.remove(arry.size() - 1); } } }
public ArrayList<ArrayList<Integer>> permuteUnique (int[] num) { ArrayList<ArrayList<Integer>> ans=new ArrayList<>(); //要先排序,从才能让相邻的元素挨着 Arrays.sort(num); ArrayList<Integer> list=new ArrayList<>(); boolean[] used=new boolean[num.length]; build(num,ans,list,used); return ans; } public void build(int[] num,ArrayList<ArrayList<Integer>> ans,ArrayList<Integer> list,boolean[] used){ if(list.size()==num.length){ ans.add(new ArrayList<>(list)); } for(int i=0;i<num.length;i++){ if(used[i]==true) continue; if(i>0&&num[i]==num[i-1]&&used[i-1]==true) continue; list.add(num[i]); used[i]=true; build(num,ans,list,used); list.remove(list.size()-1); used[i]=false; } }
import java.util.*; import java.util.Collections; import java.util.stream.Collectors; public class Solution { private ArrayList<ArrayList<Integer>> all = new ArrayList<ArrayList<Integer>>(); private ArrayList<Integer> current = new ArrayList<Integer>(); public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { int max = getMax(num); int[] countArr = new int[max + 1]; for (int idx = 0; idx < num.length; idx++) { countArr[num[idx]]++; } dfsA(num, countArr, num.length); Set<ArrayList<Integer>> set = new HashSet<ArrayList<Integer>>(all); all.clear(); all.addAll(set); Collections.sort(all, new Comparator<ArrayList<Integer>>() { public int compare(ArrayList<Integer> self, ArrayList<Integer> other) { int min = Math.min(self.size(), other.size()); for (int idx = 0; idx < min; idx++) { if (self.get(idx) != other.get(idx)) { return self.get(idx).compareTo(other.get(idx)); } } if (self.size() > other.size()) { return self.get(min + 1); } else if (self.size() < other.size()) { return other.get(min + 1); } return 0; } }); return all; } public void dfsA(int[] num, int[] countArr, int n) { if (current.size() == n) { all.add((ArrayList<Integer>) current.clone()); return; } for (int i = 0; i < n; i++) { int count = getCount(num[i]); if (count < countArr[num[i]]) { current.add(num[i]); dfsA(num, countArr, n); current.remove(current.size() - 1); } } } public int getCount(int num) { long count = current.stream().filter(item -> item == num).collect( Collectors.counting()); return Long.valueOf(count).intValue(); } public static int getMax(int[] num) { int max = Integer.MIN_VALUE; for (int idx = 0; idx < num.length; idx++) { if (max < num[idx]) { max = num[idx]; } } return max; } }
import java.util.*; public class Solution { public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { ArrayList<ArrayList<Integer>> result = new ArrayList<>(); TreeMap<Integer,Integer> treeMap = new TreeMap<>(); for(int i = 0; i<num.length;i++){ treeMap.put(num[i],treeMap.getOrDefault(num[i],0)+1); } tryMatch(treeMap,result,null); return result; } public void tryMatch(TreeMap<Integer,Integer> map, ArrayList<ArrayList<Integer>> result, ArrayList<Integer> preSequence) { TreeMap<Integer,Integer> copy = new TreeMap<>(map); for (Map.Entry<Integer,Integer> entry: map.entrySet()) {//遍历当前剩下的所有数字 Integer integer = entry.getKey(); ArrayList<Integer> p ; if (preSequence == null) { p = new ArrayList<Integer>(); } else { p = new ArrayList<Integer>(preSequence); } p.add(integer); if (map.size() > 1||entry.getValue()>1) {//数字种类大于1或者种类为1但数量大于1,需要继续递归 if(entry.getValue()<=1){//map中减少一个当前正在尝试的数字的数量(为0时直接移除这个key) copy.remove(integer); }else{ copy.put(integer,copy.get(integer)-1); } tryMatch(copy, result, p);//递归尝试 copy.put(integer,copy.getOrDefault(integer,0)+1);//恢复copy,以便操作下一个数字 } else {//不满足递归条件,视为当前尝试结束,尝试结果加入结果集 result.add(p); } } } }
import java.util.*; //正常排再去重 public class Solution { ArrayList<ArrayList<Integer>> al = new ArrayList<>(); boolean[] dp; public void back(int[] num, boolean[] dp, ArrayList<Integer> list) { if (list.size() == num.length) { al.add(new ArrayList<>(list)); return; } for (int i = 0; i < num.length; i++) { if (dp[i]) continue; dp[i] = true; list.add(num[i]); back(num, dp, list); list.remove(list.size() - 1); dp[i] = false; } } public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { Arrays.sort(num); dp = new boolean[num.length]; ArrayList<Integer> list = new ArrayList<>(); Arrays.fill(dp, false); back(num, dp, list); HashMap<ArrayList<Integer>, Integer> hs = new HashMap<>(); ArrayList<ArrayList<Integer>> al1 = new ArrayList<>(); for (int i = 0; i < al.size(); i++) { ArrayList<Integer> a = al.get(i); if (!hs.containsKey(a)) { hs.put(a, 1); al1.add(a); } } return al1; } }
import java.util.*; public class Solution { public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { ArrayList<ArrayList<Integer>> result = new ArrayList(); Arrays.sort(num); getResult(result, new ArrayList<Integer>(), num, new HashSet<>()); HashSet<String> hs = new HashSet<>(); result.removeIf(arrayList-> { StringBuilder sb = new StringBuilder(); for (Integer integer : arrayList) { sb.append(integer); } String concat = sb.toString(); boolean flag = false; if (!hs.contains(concat)) { hs.add(concat); } else { flag = true; } return flag; }); return result; } private void getResult(ArrayList<ArrayList<Integer>> result, ArrayList<Integer> ls, int[] num, HashSet<Integer> hs) { if (ls.size() == num.length) { result.add(new ArrayList<>(ls)); } else { for (int i = 0; i < num.length; i++) { if (hs.contains(i)) { continue; } ls.add(num[i]); hs.add(i); getResult(result, ls, num, hs); ls.remove(ls.size() - 1); hs.remove(i); } } } }
递归 import java.util.*; public class Solution { static ArrayList<ArrayList<Integer>> res = new ArrayList<>(); static boolean []mark; public static ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { Arrays.sort(num); mark = new boolean[num.length]; LinkedList<Integer> list = new LinkedList<>(); permute(num, list); return res; } private static void permute(int[] num, LinkedList<Integer> list) { // 递归的终结条件 if (num.length == list.size()) { if (!res.contains(list)) { res.add(new ArrayList<>(list)); } return; } for (int i = 0; i < num.length; i++) { if (mark[i]) { continue; } list.add(num[i]); mark[i] = true; permute(num, list); list.removeLast(); mark[i] = false; } } }
import java.util.*; public class Solution { public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { Arrays.sort(num); ArrayList<ArrayList<Integer>> list=new ArrayList<ArrayList<Integer>>(); ArrayList<Integer> path=new ArrayList<Integer>(); dfs(num,path,list); ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();//去重后再装入list for(int i=0;i<=list.size()-1;i++){//将list去重 if(res.contains(list.get(i))){continue;} res.add(list.get(i)); } return res; } public void dfs(int[] arr,ArrayList<Integer> path,ArrayList<ArrayList<Integer>> list){ if(path.size()==arr.length){ ArrayList<Integer> sublist=new ArrayList<Integer>(); for(int i=0;i<=path.size()-1;i++){ sublist.add(arr[path.get(i)]); } list.add(new ArrayList<Integer>(sublist)); return; } for(int i=0;i<=arr.length-1;i++){ if(path.contains(i)){continue;} path.add(i); dfs(arr,path,list); path.remove(path.size()-1); } } }