No.47全排列II

题目大意

给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]

分析

这个题只要在全排列I的基础上加一个去重操作,而这个去重操作需要注意效率。可以用Set去重,但是效率较低;可以在permutation的时候加入判断,直接去掉造成重复的交换。

代码一:Set去重

    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();

    public List<List<Integer>> permuteUnique(int[] nums) {
        if(nums==null || nums.length == 0) return res;
        permuteCore(nums,0);
        res = removeDup(res);
        return res;
    }

    private void permuteCore(int[] nums, int pos) {
        if(pos == nums.length-1) {
            for(int i=0;i<nums.length;i++)
                path.add(nums[i]);
            res.add(path);
            path = new ArrayList<>();
            //path.clear();
            return;
        } else {
            for(int i=pos;i<nums.length;i++) {
                swap(nums,pos,i);
                permuteCore(nums,pos+1);
                swap(nums,pos,i);
            }
        }
    }

    private void swap(int[] nums, int i,int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

    private List<List<Integer>> removeDup(List<List<Integer>> list) {
        //给list去重
        HashSet<List<Integer>> set = new HashSet<>();
        List<List<Integer>> r = new ArrayList<>();
        for(int i=0;i<list.size();i++) {
            if(set.add(list.get(i)))
                r.add(list.get(i));
        }
        return r;
    }

运行时间39ms,击败17.82%.

代码二:判断条件

    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> permuteUnique(int[] nums) {
        if(nums==null || nums.length == 0) return res;
        permuteCore(nums,0);
        return res;
    }
    
    private void permuteCore(int[] nums, int pos) {
        if(pos == nums.length-1) {
            List<Integer> path = new ArrayList<>();
            for(int i=0;i<nums.length;i++)
                path.add(nums[i]);
            res.add(path);
            return;
        } else {
            for(int i=pos;i<nums.length;i++) {
                if(canSwap(nums,pos,i)) {
                    swap(nums,pos,i);
                    permuteCore(nums,pos+1);
                    swap(nums,pos,i);
                }
            }
        }
    }

    private boolean canSwap(int[] nums, int i, int j) {
        for(int k=i;k<j;k++) {
            if(nums[k] == nums[j])
                return false;
        }
        return true;
    }

    private void swap(int[] nums, int i,int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

运行时间1ms,击败100%。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 个人学习批处理的初衷来源于实际工作;在某个迭代版本有个BS(安卓手游模拟器)大需求,从而在测试过程中就重复涉及到...
    Luckykailiu阅读 4,760评论 0 11
  • 思路分析: 这一题是在 「力扣」第 46 题:“全排列” 的基础上增加了“序列中的元素可重复”这一条件。因此我们还...
    李威威阅读 1,809评论 0 4
  • 安徒生奖获得者曹文轩曾经说过:“这世间所有文字,千年百年都在做着同一篇文章,生离死别。”看完《开往伊斯坦布尔的最后...
    悠游鱼阅读 353评论 1 3
  • 图面象征:白色的衣服、蓝色的披风、左手给出、右手握剑…… 意义:高不可亲近的女性、强势的女强人、懂得给出和制裁、沉...
    萌宠小恐龙阅读 414评论 0 0
  • 这几天自从有了新pad再加脖子不舒服,降低了很多在书桌前的时间,甚至回家就吃饭后躺在床上学习。 学习情况可想而知,...
    sheeeplu阅读 343评论 6 0