zoukankan      html  css  js  c++  java
  • PermutationTwo

    Description:

    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]
    ]

    Thoughts:
    这个问题和之前的permutations问题类似,区别在于这次给定的数字有重复的部分,但是我们输出的排列又不允许重复。排列的话,一个数字不允许重复使用,之前在permutions中我们用Nums.contains来规避这个问题,但是在现在这个问题中因为
    nums中有重复的数字,所以这个方法不行了,解决的办法是我们开辟一个和nums等长的boolean数组addnums,addnums中值为true,表示nums中对应位置上的数字已经被包含在排列中,就要跳过这个数字。通过这个方法我们就解决了基本的排列问题。
    还有一个问题需要解决的就是排列不允许重复,这个问题的解决方法就是跳过那些已经作为首数字出现过的数字。首先我们对于原始数组进行一次排序,然后在每次选择数字的时候判断,对于大于首字符的数字是否等于首字符,并且还没有使用过,
    如果是的话就跳过。以下是我的java代码:
    package middle;
    import java.util.*;
    public class PermutationTwo {
        public List<List<Integer>> permuteUnique(int[] nums){
            List<List<Integer>> result = new ArrayList<List<Integer>>();
            
            Arrays.sort(nums);
            ArrayList addnums = new ArrayList();
            trackBack(nums, new ArrayList(), result, addnums);
            return result;
        }
    
        private void trackBack(int[] nums, ArrayList arrayList,
                List<List<Integer>> result, ArrayList addnums) {
            // TODO Auto-generated method stub
            if(arrayList.size()==nums.length && result.contains(arrayList)==false){
                result.add(new ArrayList(arrayList));
            }
            for(int i = 0; i<nums.length;i++){
    //            if(i > 0 && nums[i] == nums[i-1]) continue;
                if(addnums.contains(i)) continue;
                arrayList.add(nums[i]);
                addnums.add(i);
                trackBack(nums, arrayList, result, addnums);
                arrayList.remove(arrayList.size() - 1);
                addnums.remove(addnums.size() - 1);
            }
        }
        
        public List<List<Integer>> permuteUniqueTwo(int[] nums){
            List<List<Integer>> result = new ArrayList<List<Integer>>();
            
            Arrays.sort(nums);
            trackBackTwo(nums, result, new ArrayList(), new boolean[nums.length]);
            
            return result;
        }
        
        private void trackBackTwo(int[] nums, List<List<Integer>> result,
                ArrayList arrayList, boolean[] use) {
            // TODO Auto-generated method stub
            if(arrayList.size() == nums.length){
                result.add(new ArrayList(arrayList));
            }else{
                for(int i = 0; i< nums.length;i++){
                    if(use[i] || i > 0&&nums[i] == nums[i-1]&&use[i-1]==false) continue;
                    use[i] = true;
                    arrayList.add(nums[i]);
                    trackBackTwo(nums, result, arrayList, use);
                    arrayList.remove(arrayList.size() - 1);
                    use[i] = false;
                }
            }
        }
    
        public static void main(String args[]){
            PermutationTwo p = new PermutationTwo();
            int[] nums = new int[]{1, -1, 1, 2, -1, 2, 2, -1};
            List<List<Integer>> list = p.permuteUniqueTwo(nums);
            System.out.println(list);
        }
    
    }



    还有第二种更加直观的解法,但是它的执行时间太慢了,leetcode上通过不了,但是为了更加便于理解我还是把它写出来。解决重复数字的问题,我是用一个ArrayList记录当前已经使用过的数字的位置,如果当前数字的位置在ArrayList中已经
    出现过了,那就说明当前的数字已经用过了,就要跳过。然后我们根据得到的排列,判断当前的排列是否包含在result中,如果包含了,也就是说当前的排列已经出现过了,那么该排列就不能加入到result中。换句话说,只有新的排列才能够出现在result
    中。以下是我的java代码:
    package middle;
    import java.util.*;
    public class PermutationTwo {
        public List<List<Integer>> permuteUnique(int[] nums){
            List<List<Integer>> result = new ArrayList<List<Integer>>();
            
            Arrays.sort(nums);
            ArrayList addnums = new ArrayList();
            trackBack(nums, new ArrayList(), result, addnums);
            return result;
        }
    
        private void trackBack(int[] nums, ArrayList arrayList,
                List<List<Integer>> result, ArrayList addnums) {
            // TODO Auto-generated method stub
            if(arrayList.size()==nums.length && result.contains(arrayList)==false){
                result.add(new ArrayList(arrayList));
            }
            for(int i = 0; i<nums.length;i++){
    //            if(i > 0 && nums[i] == nums[i-1]) continue;
                if(addnums.contains(i)) continue;
                arrayList.add(nums[i]);
                addnums.add(i);
                trackBack(nums, arrayList, result, addnums);
                arrayList.remove(arrayList.size() - 1);
                addnums.remove(addnums.size() - 1);
            }
        }
        
        public static void main(String args[]){
            PermutationTwo p = new PermutationTwo();
            int[] nums = new int[]{1, -1, 1, 2, -1, 2, 2, -1};
            List<List<Integer>> list = p.permuteUnique(nums);
            System.out.println(list);
        }
    
    }



  • 相关阅读:
    virtio前端驱动详解
    virtIO前后端notify机制详解
    virtio后端驱动详解
    centos7手动编译安装Libvirt常见问题
    手动编译安装Libvirt之后利用systemctl管理libvirtd服务
    android学习点滴一:android环境的搭建
    phpcms换域名细节
    apache配置中的小细节
    娱乐一下-加班的不归路
    qt5.3+vs2013乱码
  • 原文地址:https://www.cnblogs.com/whatyouknow123/p/7503902.html
Copyright © 2011-2022 走看看