• OJ练习第170题——最大间距(桶算法)


    最大间距

    力扣链接:164. 最大间距

    题目描述

    给定一个无序的数组 nums,返回 数组在排序之后,相邻元素之间最大的差值 。如果数组元素个数小于 2,则返回 0 。

    您必须编写一个在「线性时间」内运行并使用「线性额外空间」的算法。

    示例

    在这里插入图片描述

    Java代码(官解)

    class Solution {
        
        // 一步步详解桶算法,因为自己看了很多遍,看的简直头皮发麻
        public int maximumGap(int[] nums) {
            // n
            int n = nums.length;
    
            // 低于两个数不用比较
            if (n < 2) {
                return 0;
            }
    
            int minVal = Arrays.stream(nums).min().getAsInt();  // 计算最小值
            int maxVal = Arrays.stream(nums).max().getAsInt();  // 计算最大值
    
            // 桶区间大小因子d
            int d = Math.max(1, (maxVal - minVal) / (n - 1));
    
            // 在目标数组中需要划分的 桶 的个数, +1是为了消除d取整前的小数部分带来的误差(注意运算顺序)
            int bucketSize = (maxVal - minVal) / d + 1;
    
            /*
            * 注意:头皮开始发麻的代码要来了,抓狂抓狂
            * 刚开始对bucket这个二维数组的作用是一脸懵逼,
            * 其实就是一个bucketSize个长度为2的一维数组,这个一维数组用来记录每个区间的的最大值和最小值
            * // 0下标存的是最小值,1下标存的是最大值
            */
            int[][] bucket = new int[bucketSize][2];
    
            // 给二维数组赋初始值为-1
            for (int i = 0; i < bucketSize; ++i) {
                Arrays.fill(bucket[i], -1); // 存储 (桶内最小值,桶内最大值) 对, (-1, -1) 表示该桶是空的
            }
    
            // 遍历
            for (int i = 0; i < n; i++) {
                // 通过此运算用来判断当前元素属于哪个桶区间
                int idx = (nums[i] - minVal) / d;
    
                // 若区间为空,则此元素是第一次进来,则最大值和最小值都是它
                if (bucket[idx][0] == -1) {
                    bucket[idx][0] = bucket[idx][1] = nums[i];
                } 
                // 若区间存在其他元素,则开始下面比较
                else {
                    // 当前元素与此桶区间的最小值比较,若比最小值还小,就把最小值替换成当前元素值
                    bucket[idx][0] = Math.min(bucket[idx][0], nums[i]);
                    // 当前元素与此桶区间的最大值比较,若比最大值还大,就把最大值替换成当前元素值
                    bucket[idx][1] = Math.max(bucket[idx][1], nums[i]);
                }
            }
    
            // 经过上面的一系列操作,我们发现,这个二维数组居然出现了顺序结构
            // 现在进行最后一步
    
            int ret = 0;    // 目标值
            int prev = -1;  // 上一个下标
    
            // 开始遍历每个桶列表
            for (int i = 0; i < bucketSize; i++) {
                // 判断当前桶区间是否为空,空则跳出
                if (bucket[i][0] == -1) {
                    continue;
                }
                // 判断上一个下标是否为空,即是否第一次循环
                if (prev != -1) {
                    /*
                    * 计算上一个桶区间的最大值,与当前桶区间的的最小值的差
                    * 然后与ret目标值比较,取最大值然后替换ret值
                    */
                    ret = Math.max(ret, bucket[i][0] - bucket[prev][1]);
                }
                prev = i;   // 上一个下标自增
            }
            return ret;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77

    详解分析来源:https://leetcode.cn/problems/maximum-gap/solutions/498428/zui-da-jian-ju-by-leetcode-solution/comments/682423

  • 相关阅读:
    Redis过期删除策略和内存淘汰策略
    音频pop音的数学与物理解释
    AppStore审核被拒:other-other,过审核、不过审的经历
    Acwing-反转链表
    【教学类-12-02】20221105《连连看12*4-不重复24个)(小班主题《白天与黑夜》)
    05 | 基础篇:某个应用的CPU使用率居然达到100%,我该怎么办?笔记
    简单理解MySQL的存储引擎
    C++ 组合模式
    代码随想录打卡—day59—【单调栈】— 9.5 单调栈2
    zigbee笔记:七、zigbee系统电源管理与睡眠唤醒
  • 原文地址:https://blog.csdn.net/weixin_45662626/article/details/132834032