Permutations II

Question: 

Given a list of numbers with duplicate number in it. Find all unique permutations.

 
Example:

For numbers [1,2,2] the unique permutations are:

[

    [1,2,2],

    [2,1,2],

    [2,2,1]

]

 
Analysis:
这个问题和subsets很类似,这里要找的是所有排列的情况,同样是用DFS搜索求解。从空集开始,每次往list中加入一个元素,当list的长度和nums的长度一致,就说明找到了一种排列,将其加入result中。重复该过程,直到没有元素可以添加。这里比较tricky的地方是:先添加第一个2和先添加第二个2得到的结果是一样的,所以就产生了重复。为了解决这一问题,引入了visited数组,i是nums中元素的下标,它的作用是记录nums中的元素是否已经被访问过。
举个例子:
nums = [1,2(1),2(2)],括弧中的数字代表第一个2和第二个2。
当程序执行到某一时刻,list = [1, 2(2)],这时与之对应的visited = [true, false, true]。我们发现这时(i = 2),这条判断语句 nums.get(i) == nums.get(i - 1) && !visited[i - 1] 就会返回true,然后跳过该层循环执行下一层。这个判断的意思就是:当访问的当前元素与它前一个元素相等,并且前一个元素还未被访问,换句话说就是先访问的是第二个2,也就是list = [1, 2(2), ..., ...]这种情况。我们可以推测出,在这之前,肯定有一种情况是先访问第一个2的,也就是list = [1, 2(1), ..., ...]。而这两种情况所得出的结果是相等的,所以我们只要continue跳过就行了。
 
Code:
 1 class Solution {
 2     /**
 3      * @param nums: A list of integers.
 4      * @return: A list of unique permutations.
 5      */
 6     public ArrayList<ArrayList<Integer>> permuteUnique(ArrayList<Integer> nums) {
 7         ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
 8         ArrayList<Integer> list = new ArrayList<Integer>();
 9         if(nums == null || nums.size() == 0) {
10             return result;
11         }
12         
13         Collections.sort(nums);
14         boolean[] visited = new boolean[nums.size()];
15         permuteUniqueHelper(result, list, nums, visited);
16         return result;
17     }
18     
19     public void permuteUniqueHelper(ArrayList<ArrayList<Integer>> result,
20                               ArrayList<Integer> list,
21                               ArrayList<Integer> nums,
22                               boolean[] visited) {
23         if(list.size() == nums.size()) {
24             result.add(new ArrayList<Integer>(list));
25         }
26         
27         for(int i = 0; i < nums.size(); ++i) {
28             if(visited[i] || (i > 0 && nums.get(i) == nums.get(i - 1) && !visited[i - 1]))
29                 continue;
30                 
31             visited[i] = true;    
32             list.add(nums.get(i));
33             permuteUniqueHelper(result, list, nums, visited);
34             list.remove(list.size() - 1);
35             visited[i] = false;
36         }
37     }
38 }

Complexity:
时间复杂度是O(n! * n), 因为有n!种情况,每种情况耗时n。空间复杂度是O(n)。
 
 

posted on 2015-11-29 09:03  BillZ  阅读(181)  评论(0编辑  收藏  举报

导航