为什么80%的码农都做不了架构师?>>>   

问题:

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

For example,
[1,1,2] have the following unique permutations:

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

解决:

① 与Permutations类似,因为包含重复的数字,所以我们要对重复的排列序列进行排除,首先我们对数组进行排序,判断当前遍历到的数是否与前一个数相同,使用一个标记数组boolean[] used来判断前一个相同的值是否被使用了,若正在被使用,说明正在处于前一个值得递归过程中,当前值不能被跳过;若没有被使用,说明这个值已经作为头部被使用过了,跳过当前值以排除重复。使用一个链表pre来记录之前排列好的值,需要注意的是,遍历完成一个排列之后,需要还原pre以进行下一次排列。

public class Solution { //7ms
    public List<List<Integer>> permuteUnique(int[] nums) {   
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        if(nums == null || nums.length == 0) return res;
        boolean [] used = new boolean[nums.length];
        List<Integer> pre = new ArrayList<>();
        Arrays.sort(nums);
        dfs(nums,used,pre, res);
        return res;
    }
    private void dfs(int[] nums, boolean [] used, List<Integer> pre, List<List<Integer>> res){
        if(pre.size() == nums.length){
            res.add(new ArrayList<>(pre));//若直接res.add(pre),会导致集合为空[[],[],[],[],[],[]]
            return;
        }
        for(int i = 0; i < nums.length; i ++){
            if(i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;//去重
            if(! used[i]){
                used[i] = true;
                pre.add(nums[i]);//加入当前值
                dfs(nums,used,pre,res);//递归查找值
                pre.remove(pre.size() - 1);//还原前一个排列,继续查找排列
                used[i] = false;
            }
        }
    }
}

② 另外,我们可以使用一个临时链表cur来记录加入当前值之后的排列,这样,就可以避免还原pre。

public class Solution { //11ms
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> permuteUnique(int[] nums) {
        int len = nums.length;
        if(len == 0) return res;
        Arrays.sort(nums);
        boolean[] used = new boolean[len];
        List<Integer> pre = new ArrayList<>();
        dfs(nums,used,pre);
        return res;
    }
    private void dfs(int[] nums,boolean[] used,List<Integer> pre){
        if(pre.size() == nums.length){//完成一个排列
            //res.add(new ArrayList<Integer>(pre));
            res.add(pre);
            return;
        }
        for(int i = 0;i < nums.length;i ++){
            if(i > 0 && nums[i] == nums[i - 1] && ! used[i - 1]) continue;//前一个数没有被选中,说明在前一个数时已经完成了以该数为开头的排列
            List<Integer> cur = new ArrayList<Integer>(pre);//这样就不需要还原pre了,因为pre与cur分开了
            if(! used[i]){
                cur.add(nums[i]);
                used[i] = true;
                dfs(nums,used,cur);
                used[i] = false;
            }
        }
    }
}

③ 直接使用backtrack(DFS)而不用使用标记位。并且不需要对数组排序。以{1,1,2}为例进行递归分析如下:

class Solution { //6ms
    public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        dfs(nums,0,res);
        return res;
    }
    public void dfs(int[] nums,int i,List<List<Integer>> res){//i表示当前排列的开头在原固定数组中的位置
        //找到转换完成的链表,将其存入链表中
        if(i == nums.length - 1){//递归结束条件,得到一个排列
            List<Integer> tmp = new ArrayList<>();
            for (int j = 0;j < nums.length ;j ++ ) {
                tmp.add(nums[j]);
            }
            res.add(tmp);
        }else{//没有完成排列
            for (int j = i;j < nums.length ;j ++ ){//排列i之后的数
                if(containsRepeated(nums,i,j)) continue;//判断i到j之间是否存在重复,如果存在,则不需要交换和递归,因为这是同一个排列  
                //若不存在重复,则进行以下排列              
                swap(nums,i,j); //交换开头,若j=i表示固定当前开头计算排列,否则表示以当前值为开头的已经排列完了
                dfs(nums,i + 1,res);//改变数组的开头为原数组中i之后的第一个数,递归得到它的全排列
                swap(nums,i,j);//递归完成,还原交换的数组
            }
        }
    }
    public boolean containsRepeated(int[] nums,int i,int j){
        for (int k = i;k <= j - 1 ;k ++ ) {//若i=j,则无法进入该循环,直接返回false;
            if(nums[k] == nums[j]) return true;
        }
        return false;
    }
    public void swap(int[] nums,int i,int j){
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

转载于:https://my.oschina.net/liyurong/blog/1528741

全排列(去除重复)Permutations II相关推荐

  1. [LeetCode] Permutations II 全排列之二

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  2. 【数字全排列】LeetCode 47. Permutations II

    LeetCode 47. Permutations II Solution1:我的答案 笨蛋方法:和第46题的思路差不多,把vector换成了set就OK啦~~~ class Solution { p ...

  3. LeetCode:Permutations, Permutations II(求全排列)

    Permutations Given a collection of numbers, return all possible permutations. For example,  [1,2,3]  ...

  4. list元素求和_LeetCode刷题实战82:删除排序链表中的重复元素 II

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试.所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家 ...

  5. R语言dplyr包distinct函数去除重复数据行实战

    R语言dplyr包distinct函数去除重复数据行实战 目录 R语言dplyr包distinct函数去除重复数据行实战 #导入dplyr包 #仿真数据

  6. [华为机试真题][2014]62.去除重复字符并排序

    题目 描述: 去除重复字符并排序 运行时间限制: 无限制 内容限制: 无限制 输入: 字符串 输出: 去除重复字符并排序的字符串 样例输入: aabcdefff 样例输出: abcdef 代码 /*- ...

  7. 算法---删除排序链表中的重复元素 II

    删除排序链表中的重复元素 II 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 .返回 已排序的链表 . 输入:head = [1,2,3,3,4,4,5] ...

  8. lintcode :Remove Duplicates from Sorted Array II 删除排序数组中的重复数字 II

    题目: 删除排序数组中的重复数字 II 跟进"删除重复数字": 如果可以允许出现两次重复将如何处理? 样例 给出数组A =[1,1,1,2,2,3],你的函数应该返回长度5,此时A ...

  9. linux shell 文件去除重复行

    原始文本文件 $ cat test jason jason jason fffff jason 方法一:sort -u 去除重复后 sort -u test fffff jason 注意顺序被打乱 方 ...

  10. python3 文本文件内容去除重复行

    环境:python3.8 import shutil# 文件去除重复行 def remove_duplicates(path):lines_seen = set()outfile = open(f&q ...

最新文章

  1. L1-008.求整数段和
  2. MIT | 一种可解释的PPI预测模型
  3. About Instruments
  4. 数据结构:希尔排序(shell sort)
  5. 【AwayPhysics学习笔记】:Away3D物理引擎的简介与使用
  6. postgresql数据表增删改:使用pgadmin和SQL的方式实现
  7. 极客班C++ STL(容器)第二周笔记
  8. 从零写一个编译器(二):语法分析之前置知识
  9. Ansible Tower 入门 1 - 配置主机清单和访问凭证
  10. 【线程】——初识线程
  11. C Tricks(十一)—— 排除一个二维数组的边界
  12. JavaScript事件冒泡和事件委托
  13. Android AdapterViewFlipper
  14. [集成IronPython] 使用Module扩展IronPython
  15. 为什么csgo一直显示连接官方服务器失败,CSGO提示连接任意官方服务器失败怎么办?五大详细解决方法看这里!...
  16. win10固态硬盘分区 整数_电脑硬盘分区大小多少才合理【详细介绍】
  17. IOS视频分解图片、图片合成视频
  18. 【Java】JDK目录介绍
  19. discuzdiy图片模块_dz论坛diy教程,discuz论坛DIY详细教程 论坛diy教程
  20. mac的rubywoo怎么读_MAC大热色号 RUBY WOO

热门文章

  1. 使用简单的5个步骤设置 Web服务器集群
  2. 创建者模式 builder
  3. 什么是跨域(定义理解错误)
  4. [读书笔记] 美的历程
  5. 斐波那契数列(二)--矩阵优化算法
  6. java中p.name_spring如何使用命名空间p简化bean的配置
  7. c#网页自动化脚本语言,c# – 创建用于创建网页的脚本语言
  8. 什么叫大地高_什么才叫睡得好?睡觉能满足这5个标准,说明睡眠质量高
  9. react 导航条选中颜色_调整安卓手机的颜色以更好地查看一切
  10. java swt最小化到托盘_SWT 中实现最小化到托盘图标,并只能通过托盘的弹出菜单关闭程序...