码迷,mamicode.com
首页 > 其他好文 > 详细

[LintCode] Permutations II

时间:2015-10-29 00:15:14      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:

Permutations II

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]

]

Challenge

Do it without recursion.

 

SOLUTION 1: 

递归recursion:

难点当然是去重,所以其他的就不说了,完全参照subsets理解就可以。

考虑去重时候的想法比较简单,首先要模拟这个递归树,发现什么情况下会重复,什么情况下要跳过这一步(其实就是加速DFS)。

这题:( 1, 2, 2)

                               []

                   /           |         \

            [1]             [2]            [2](重复)

          /    \           /      \               \

   [1,2]  [1,2]     [2,1]   [2,2]         [2,1](重复)

   /         (重复)  /             \                 \

[1,2,2]          [2,1,2]        [2,2,1]            .....(重复)

最后只有三个是可用的,其他的都重复了。

这时候不太好直接看出来,所以引入一个visited,在递归的时候,走过的点标1,没走过就是0。比如最左边分支,visited里面发现以前走过2,那就不走这一步了。再比如最右边分支,走到2就发现以前走过,就直接跳过挣个右侧分支。                                          在这一层访问过  && 前一个大的分支遍历了一次,并且,这个数跟前一个数重合

程序的表示visited.contains(nums[i])可以用map表示,也可以用数组表示,(visited[i] == 1 && (visited[i - 1] == 0         &&       nums[i] == nums[i -1]))

程序如下(答案参照九章算法:http://www.jiuzhang.com/solutions/permutations-ii/ 具体请看网页):

技术分享
public class Solution {
    public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        if(num == null || num.length == 0)
            return result;
        ArrayList<Integer> list = new ArrayList<Integer>();
        int[] visited = new int[num.length];
        
        Arrays.sort(num);
        helper(result, list, visited, num);
        return result;
    }
    
    public void helper(ArrayList<ArrayList<Integer>> result, ArrayList<Integer> list, int[] visited, int[] num) {
        if(list.size() == num.length) {
            result.add(new ArrayList<Integer>(list));
            return;
        }
        
        for(int i = 0; i < num.length; i++) {
            if (visited[i] == 1 || (i != 0 && num[i] == num[i - 1] && visited[i - 1] == 0)){
        // 上面的判断其实并不影响最终结果,目的是为了让dfs能更快
        /*
            上面这一连串判断条件,重点在于要能理解!visited.contains(i-1)
            要理解这个,首先要明白i作为数组内的序号,i是唯一的
            给出一个排好序的数组,[1,2,2]
            第一层递归            第二层递归            第三层递归
            [1]                    [1,2]                [1,2,2]
                序号:[0]                 [0,1]            [0,1,2]
            这种都是OK的,但当第二层递归i扫到的是第二个"2",情况就不一样了
            [1]                    [1,2]                [1,2,2]            
                         序号:[0]                [0,2]                [0,2,1]
            所以这边判断的时候!visited.contains(0)就变成了true,不会再继续递归下去,跳出循环
            步主要就是为了去除连续重复存在的,很神奇反正 = =||
    */
                continue;
            }
            visited[i] = 1;
            list.add(num[i]);
            helper(result, list, visited, num);
            list.remove(list.size() - 1);
            visited[i] = 0;
        }
    }    
}
View Code

 

 

[LintCode] Permutations II

标签:

原文地址:http://www.cnblogs.com/tritritri/p/4919120.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!