47.Permutations II

題目連接:https://leetcode.com/problems/permutations-ii/description/數組

題目大意:全排列一串數(有重複數字)。ide

法一:也便是46題的法一,只加了一行代碼。代碼以下(耗時499ms):spa

 1     public List<List<Integer>> permute(int[] nums) {
 2         List<List<Integer>> list = new ArrayList<List<Integer>>();
 3         int[] vis = new int[nums.length];
 4         Arrays.fill(vis, 0);//初始化全爲0
 5         List<Integer> tmp = new ArrayList<Integer>();
 6         dfs(list, nums, vis, tmp);
 7         return list;
 8     }
 9     public static void dfs(List<List<Integer>> list , int[] nums, int[] vis, List<Integer> tmp) {
10     //    System.out.println(tmp);
11         if(tmp.size() == nums.length) {
12             if(!list.contains(tmp))
13                 list.add(new ArrayList<Integer>(tmp));//這裏必定要用new以後再加入到list中,不然list集合會是空值
14             return;
15         }
16         for(int i =0 ; i < nums.length; i++) {
17             if(vis[i] == 0) {
18                 vis[i] = 1;
19                 tmp.add(nums[i]);
20                 dfs(list, nums, vis, tmp);
21                 tmp.remove(tmp.size() - 1);//刪除最後一個元素
22                 vis[i] = 0;
23             }
24         }
25     }
View Code

法二:也就是46題的法二,只加了一行代碼,利用List特性判重:list.contains()。代碼以下(耗時78ms):code

 1     public List<List<Integer>> permute(int[] nums) {
 2         LinkedList<List<Integer>> res = new LinkedList<List<Integer>>();
 3         res.add(new ArrayList<Integer>());//加一個空的list進去,以保證下面size在第一次的時候就爲1,從而保證後面的計算
 4         for(int n : nums) {//遍歷nums數組值
 5             for(int size = res.size(); size > 0; size--) {//查看結果集res中已經包含幾個序列
 6                 List<Integer> tmp = res.pollFirst();//取出結果集res中的每一個序列
 7                 for(int i = 0; i <= tmp.size(); i++) {//對於取出的序列,在每個位置都嘗試加入當前nums數組值,這裏的i表示當前取出序列的第i位,好比取出的序列是1,接下來就要在1以前及1以後加入2
 8                     List<Integer> resIn = new ArrayList<Integer>(tmp);//每個位置都新初始化剛取出的序列,這樣保證能在原始取出序列的基礎上增添數值
 9                     resIn.add(i, n);//在第i位加入數值n
10                 //    System.out.println(resIn);
11                     if(res.contains(resIn)) continue;
12                     res.add(resIn);//這裏由於每從結果集中取出一個序列就是清空一個序列,因此這裏add的時候就是一個全新的序列
13                 }
14             }
15         }
16         return res;
17     }
View Code

 剪枝:前面的都是把全部的排列都計算完以後再考慮是否加入結果集中,而下面這個是在計算排列的時候就進行剪枝。這裏剪枝利用先後元素的相等性來判斷剪枝。正確的剪枝真的能夠減小好多的時間複雜度。具體以下(耗時9ms):blog

 1     public List<List<Integer>> permuteUnique(int[] nums) {
 2         List<List<Integer>> list = new ArrayList<List<Integer>>();
 3         int[] vis = new int[nums.length];
 4         Arrays.fill(vis, 0);//初始化全爲0
 5         List<Integer> tmp = new ArrayList<Integer>();
 6         Arrays.sort(nums);//必定要先排序,這樣才能保證下面剪枝的時候,相同的元素相鄰
 7         dfs(list, nums, vis, tmp);
 8         return list;
 9     }
10     public static void dfs(List<List<Integer>> list , int[] nums, int[] vis, List<Integer> tmp) {
11     //    System.out.println(tmp);
12         if(tmp.size() == nums.length) {
13             list.add(new ArrayList<Integer>(tmp));//這裏必定要用new以後再加入到list中,不然list集合會是空值
14             return;
15         }
16         for(int i =0 ; i < nums.length; i++) {
17             //套路剪枝,去除重複元素
18             //選取下一個元素的時候,要查看這個元素的前一個元素是否和它相同,若是相同並且沒有使用過,就不用選取這個元素,由於若是選取了這個元素,所得的結果被包含於選取了前一個相同元素的結果中。
19             if(i > 0 && vis[i - 1] == 0 && nums[i - 1] == nums[i]) {
20                 continue;
21             }
22             else if(vis[i] == 0){
23                 vis[i] = 1;
24                 tmp.add(nums[i]);
25                 dfs(list, nums, vis, tmp);
26                 tmp.remove(tmp.size() - 1);//刪除最後一個元素
27                 vis[i] = 0;
28             }
29         }
30     }
View Code
相關文章
相關標籤/搜索