164. Maximum Gap

一、题目

  1、审题

  

 

  2、分析

    给出一个无序的整形数组,求其有序时相邻元素的最大差值为多大。

 

二、解答

  1、思路:

    方法一、

      桶排序。

      ①、首先找出数组中最大元素、最小元素: max 、min;

      ②、去除 max、min 时数组剩下 N - 2 个元素,取 N - 1 个桶进行存放,则一个桶内存放元素范围为: ceiling[(max - min ) / (N - 1)] ;且第 k 个桶存放的数值大小范围为 [min+ (k-1)gap, min+ k*gap);

      ③、可知至少有一个桶为空着的,所以相邻元素的最大差值必定在不同的桶之间,也即在前一个有效桶(非空)的最大值与后一个有效桶(非空)的最小值的差。

    public int maximumGap2(int[] nums) {
        
        if(nums == null || nums.length < 2)
            return 0;
        
        int len = nums.length;
        int maxVal = Integer.MIN_VALUE;
        int minVal = Integer.MAX_VALUE;
        
        for (int i = 0; i < len; i++) {
            maxVal = Math.max(maxVal, nums[i]);
            minVal = Math.min(minVal, nums[i]);
        }
        
        // 取 len - 1 个桶时(去除 maxVal、minVal 后剩下 len - 2个数,必有一个空桶), 求解桶间最小的差值,向上取整
        int gap = (int) Math.ceil((double)(maxVal - minVal)/(len - 1));
        int[] maxBuk = new int[len - 1];
        int[] minBuk = new int[len - 1];
        
        Arrays.fill(maxBuk, Integer.MIN_VALUE);
        Arrays.fill(minBuk, Integer.MAX_VALUE);
        // 桶映射
        for(int val: nums) {
            if(val == minVal || val == maxVal)
                continue;
            int idx = (val - minVal) / gap;
            maxBuk[idx] = Math.max(maxBuk[idx], val);
            minBuk[idx] = Math.min(minBuk[idx], val);
        }
        
        //求解最大gap,最大差值位于后桶的min-前桶的max
        int maxGap = Integer.MIN_VALUE;
        int pre = minVal;
        for (int i = 0; i < len - 1; i++) {
            
            if(maxBuk[i] == Integer.MIN_VALUE && minBuk[i] == Integer.MAX_VALUE)
                continue;
            maxGap = Math.max(maxGap, minBuk[i] - pre);
            pre = maxBuk[i];
            
        }
        maxGap = Math.max(maxGap, maxVal - pre);
        return maxGap;
    }

 

  方法二、

    基数排序

    动画演示:https://www.cs.usfca.edu/~galles/visualization/RadixSort.html

    ①、找出数组最大值,用于控制循环;

    ②、运用技术排序,从最低位到最高位进行排序;

    ③、 (nums[i] / exp) % 10 用于获取数字排序的数值, 且数字本身就是访问 count 数组的索引 ;

      count 数组存储访问 AUX 的索引,根据 Aux 当前的顺序存储排序后的数字。

    
    public int maximumGap3(int[] nums) {
        
        if(nums == null || nums.length < 2)
            return 0;
        
        int max = nums[0];
        for (int i = 1; i < nums.length; i++) 
            max = Math.max(max, nums[i]);
        
        int exp = 1;    // 1, 10, 100, 1000
        int R = 10;
        
        int[] aux = new int[nums.length];
        
        while(max / exp > 0) {    // Go through all digits from LSB to MSB
            int[] count = new int[R];
            
            for (int i = 0; i < nums.length; i++) 
                count[(nums[i] / exp) % 10]++;
            
            for (int i = 1; i < count.length; i++) 
                count[i] += count[i - 1];
            
            for (int i = nums.length - 1; i >= 0; i--) 
                aux[--count[(nums[i] / exp) % 10]] = nums[i];
            
            for (int i = 0; i < nums.length; i++) 
                nums[i] = aux[i];
            
            exp *= 10;
        }
        
        max = 0;
        for (int i = 1; i < aux.length; i++) 
            max = Math.max(max, aux[i] - aux[i - 1]);
            
        return max;
    }

 

posted @ 2018-10-15 11:21  skillking2  阅读(259)  评论(0编辑  收藏  举报