力扣第164题-最大间距

171 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情

前言

力扣第164题 最大间距 如下所示:

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

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

示例 1:

输入: nums = [3,6,9,1]
输出: 3
解释: 排序后的数组是 [1,3,6,9]  ,  其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。

一、思路

题目意思很简单:将无序数组排好序后,找到相邻元素最大的插值。我刚开始就是按照题目意思分为两个步骤实现了:

  1. 使用 Arrays.sort 排序数组 nums
  2. 再遍历一遍数组求出相邻元素间最大的插值

代码和结果如下所示:

image.png

image.png

出乎意外的顺利,甚至还没有写测试用例就已经通过了。我就直奔题解去,一看官方原来是想使用 基数排序桶排序,使得题目的时间复杂度为 O(N)

在这里我们主要说明一下 基数排序 在此题的应用与流程

基数排序

先了解一下 基数排序 的基本思想:先找到数组中的最大值,然后个位、十位、百位的顺序来排序数组。此处以 nums = {30,61,93,100, 10} 作为例子

image.png

  1. 取出数组的个位,再按照个位的大小进行排序

image.png

排序后的结果

image.png

  1. 在个位数排序好的基础上,再对十位进行排序

image.png

排序好如下所示(虽然实际上无变化)

image.png

  1. 最后在个十位排序号的情况下,对百位进行排序

image.png

排序后

image.png

总的过程如下所示:

image.png

综上所述,基数排序 就是按照位数上的值从小到大的排序元素。

二、实现

实现代码

实现代码与思路中保持一致

public int maximumGap(int[] nums) {
    int n = nums.length;
    if (n < 2) {
        return 0;
    }
    int cur = 1;   // 当前对比的位
    int[] temp = new int[n];
    int maxVal = getMax(nums);

    while (maxVal >= cur) {
        // 0 ~ 9 计数
        int[] count = new int[10];
        for (int i = 0; i < n; i++) {
            int digit = (nums[i] / cur) % 10;
            count[digit]++;
        }
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }
        for (int i = n - 1; i >= 0; i--) {
            int digit = (nums[i] / cur) % 10;
            // 当前位在元素对应的位置
            int p = count[digit] - 1;
            temp[p] = nums[i];
            // 用过一次了,记得减去
            count[digit]--;
        }
        System.arraycopy(temp, 0, nums, 0, n);
        cur *= 10;
    }

    int ret = 0;
    for (int i = 1; i < n; i++) {
        ret = Math.max(ret, nums[i] - nums[i - 1]);
    }
    return ret;
}

public int getMax(int[] nums) {
    int ret = nums[0];
    for (int i = 1; i < nums.length; i++)
        if (ret < nums[i]) ret = nums[i];
    return ret;
}

测试代码

public static void main(String[] args) {
    int[] nums = {30,61,93,100, 10};
    new Number164().maximumGap(nums);
}

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~