每天一题LeetCode【第34天】

T47. Permutations II【Medium

题目

给出一个可以包含重复数字的数字集,返回所有可能的不重复排列组合。

例如,
[1,1,2] 有如下的排列组合:

[
  [1,1,2],
  [1,2,1],
  [2,1,1]
]

思路

这题的大体想法和上题一样,不过除了递归,这题还要对重复怎么判断进行处理,以及防止重复排列组合的出现。

① 递归

思路和上一题差不多,如下:

排列组合(1 2 3)
= 1 + 排列组合(2 3)∪ 2 + 排列组合(1 3)∪ 3 + 排列组合(1 2)
排列组合(2 3)
= 2 + 排列组合(3)∪ 3 + 排列组合(2)
= 23 ∪ 32 

可以看出在数字只有一个的时候到了递归的终点

② 重复判别

上一题是直接看这个数有没有用过,那是基于这个数只出现一遍,而在这题可以出现重复的数字这个方法就不可用了。这个 Solution 用了什么解决方法呢,看下面:

boolean[] used = new boolean[nums.length];

建立了一个 boolean 的数组和 nums 中的数一一对应,然后用

used[i]=true;
used[i]=false;

的设置来表示这个数是否用过

然后用在循环中加入下面的语句来跳过用过的数字

if(used[i]) continue;

③ 排除重复排列组合

造成重复排列组合的原因可以动手写一下看看~

避免这种重复的方法在于后面重复的数不能排在前面重复的数前面(可能有点绕,最好动手写写看)。

代码则是很简单,像下面这样:

if(i>0 &&nums[i-1]==nums[i] && !used[i-1]) continue;

因为已经排好序了,所以若 nums[i-1]==nums[i] 和 !used[i-1] 则代表它之前的重复的数没有被用到,这时,跳过这次循环,因为它也不应该被用。

另外,不能写成

if(i>0 &nums[i-1]==nums[i] & !used[i-1]) continue;

可以想一下原因~我在补充里说!

代码

代码取自 Top Solution,稍作注释

public List<List<Integer>> permuteUnique(int[] nums) {
        //建立要返回的数据形式
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        //若为空,直接返回
        if(nums==null || nums.length==0) return res;
        //建立 used 数组来判断这个数字是否用过
        boolean[] used = new boolean[nums.length];
        List<Integer> list = new ArrayList<Integer>();
        //排序
        Arrays.sort(nums);
        dfs(nums, used, list, res);
        return res;
    }

public void dfs(int[] nums, boolean[] used, List<Integer> list, List<List<Integer>> res){
        //若所有元素都用到了(达到长度)则加到 ArrayList 里面
        if(list.size()==nums.length){
            res.add(new ArrayList<Integer>(list));
            return;
        }
        for(int i=0;i<nums.length;i++){
            //若用到过这个数字了,则跳过本次循环
            if(used[i]) continue;
            //用这句来避免重复
            if(i>0 &&nums[i-1]==nums[i] && !used[i-1]) continue;
            //设置为true代表已经用过
            used[i]=true;
            //下面四行是递归,看和上一题差不多,看"思路"里
            list.add(nums[i]);
            dfs(nums,used,list,res);
            used[i]=false;
            list.remove(list.size()-1);
        }
    } 

补充

关于

if(i>0 &&nums[i-1]==nums[i] && !used[i-1]) continue;

为什么要用 "&&" 而不用 "&"?

我们可以尝试先把 "&&" 改成 "&",然后发现会报错!

为什么呢?我的编译器不爱我了吗?

这要先讲一下两者的区别:

&&和&都是表示与,区别是&&只要第一个条件不满足,后面条件就不再判断。而&要对所有的条件都进行判断。

因为当用了 && 时,执行 i>0 为 false 时就不往下执行了,而用 & 时会把这三个都执行一遍,在执行

nums[i-1]==nums[i]

的时候 nums[i-1] 是 nums[-1],会报 ArrayIndexOutOfBoundsException 的错误。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,662评论 0 33
  • LeetCode 刷题随手记 - 第一部分 前 256 题(非会员),仅算法题,的吐槽 https://leetc...
    蕾娜漢默阅读 16,520评论 2 36
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,296评论 18 399
  • subset-DFS+Backtracking系列,有模板方法可以记 例1:leetcode 78. Subse...
    暗黑破坏球嘿哈阅读 5,805评论 1 3
  • "月岭真是个苦命的女人"。同为服务员的老胡一边擦着玻璃一边跟我说着。 月岭,目前的工作是餐厅服务员,34岁,两个孩...
    达文溪阅读 242评论 0 1