• LintCode 16. 带重复元素的排列


    写在前面:这题和全排列不含重复元素的那题几乎一样,我比较垃圾,就用HashSet去掉了重复的元素但是看了九章算法的答案也没看懂,他写的很有感觉。

    用了hash,本来想着怎么写hashcode()和equal()方法的,哪知道都帮我写好了,Integer类型的元素存储在List中的hashcode()和equal()的方法可以直接使用
    下面是源代码和我的测试代码:

    //这是ArrayList父类public abstract class AbstractList<E>中的源码
    public int hashCode() {
            int hashCode = 1;
            for (E e : this)
                hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
            return hashCode;
        }
    
    public boolean equals(Object o) {
            if (o == this)
                return true;
            if (!(o instanceof List))
                return false;
    
            ListIterator<E> e1 = listIterator();
            ListIterator<?> e2 = ((List<?>) o).listIterator();
            while (e1.hasNext() && e2.hasNext()) {
                E o1 = e1.next();
                Object o2 = e2.next();
                if (!(o1==null ? o2==null : o1.equals(o2)))
                    return false;
            }
            return !(e1.hasNext() || e2.hasNext());
        }
    @Test
        public void test() {
            List<Integer> list1 = new ArrayList<>();
            list1.add(1);
            List<Integer> list2 = new ArrayList<>();
            list2.add(2);
            List<Integer> list3 = new ArrayList<>();
            list3.add(1);
    
            System.out.println(list1.hashCode());
            System.out.println(list2.hashCode());
            System.out.println(list3.hashCode());
            System.out.println(list1==list2);
            System.out.println(list1==list3);
            System.out.println(list2==list3);
            System.out.println(list1.equals(list2));
            System.out.println(list1.equals(list3));
            System.out.println(list2.equals(list3));
            }
    //运行结果
    //        32
    //        33
    //        32
    //        false
    //        false
    //        false
    //        false
    //        true
    //        false
    

    下面是我写的代码,只是使用HashSet去重

    import org.junit.Test;
    
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    
    public class permuteUnique {
        /**
         * @param : A list of integers
         * @return: A list of unique permutations
         * <p>
         * 16. 带重复元素的排列
         * 给出一个具有重复数字的列表,找出列表所有不同的排列。
         * <p>
         * 样例
         * 给出列表 [1,2,2],不同的排列有:
         * <p>
         * [
         * [1,2,2],
         * [2,1,2],
         * [2,2,1]
         * ]
         * 挑战
         * 使用递归和非递归分别完成该题。
         * <p>
         * 写过不含重复元素的全排列,这提是含重复元素的,应该相差不大
         */
        public List<List<Integer>> permuteUnique(int[] nums) {
            // write your code here
            HashSet<List<Integer>> hashResult = new HashSet<>();
            List<List<Integer>> result = new ArrayList<>();
            List<Integer> list = new ArrayList<>();
            if (nums == null) {
                return result;
            }
            if (nums.length == 0) {
                result.add(list);
                return result;
            }
            boolean[] color = new boolean[nums.length];
            for (int i = 0; i < nums.length; i++) {
                color[i] = false;
            }
            dfs(hashResult, list, nums, color);
            result = new ArrayList<>(hashResult);
            return result;
        }
    
    
        public void dfs(HashSet<List<Integer>> hashResult, List<Integer> list, int[] nums, boolean[] color) {
            if (list.size() == nums.length) {
                hashResult.add(new ArrayList<>(list));
                return;
            }
    
            for (int i = 0; i < nums.length; i++) {
                if (color[i] == false) {
                    list.add(nums[i]);
                    color[i] = true;
                    dfs(hashResult, list, nums, color);
                    color[i] = false;
                    list.remove(list.size() - 1);
                }
            }
        }
    
        @Test
        public void testPermuteUnique() {
    //        List<List<Integer>> result = permuteUnique(new int[]{1, 2, 2});
    //        for (int i = 0; i < result.size(); i++) {
    //            System.out.println(result.get(i).toString());
    //        }
    
        }
    }
    

    下面是九章的答案,写的很难懂,狠巧妙
    和没有重复元素的 Permutation 一题相比,只加了两句话:

    Arrays.sort(nums) // 排序这样所有重复的数
    if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) { continue; } // 跳过会造成重复的情况

        public List<List<Integer>> permuteUnique(int[] nums) {
            List<List<Integer>> results = new ArrayList<>();
            if (nums == null) {
                return results;
            }
    
            Arrays.sort(nums);
            dfs(nums, new boolean[nums.length], new ArrayList<Integer>(), results);
    
            return results;
        }
    
    
          private void dfs(int[] nums,
                         boolean[] visited,
                         List<Integer> permutation,
                         List<List<Integer>> results) {
            if (nums.length == permutation.size()) {
                results.add(new ArrayList<Integer>(permutation));
                return;
            }
    
            for (int i = 0; i < nums.length; i++) {
                if (visited[i]) {
                    continue;
                }
                if (i > 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
                    continue;
                }
    
                permutation.add(nums[i]);
                visited[i] = true;
                dfs(nums, visited, permutation, results);
                visited[i] = false;
                permutation.remove(permutation.size() - 1);
            }
        } 
  • 相关阅读:
    连接数据库及出现System.AccessViolationException错误的解决方法
    WCF REST 工作总结
    jquery easyui 扩展验证
    正则表达式语法
    SQL select语句执行顺序
    添加头文件afxwin.h后引起异常的解决办法
    imagej基本操作
    医学图像处理(一)
    灰度图像的自动阈值分割(Otsu 法)
    关于glog使用中遇到的问题
  • 原文地址:https://www.cnblogs.com/wei1/p/9582055.html
Copyright © 2020-2023  润新知