[路飞]_程序员必刷力扣题: 164. 最大间距

737 阅读2分钟

「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战

164. 最大间距

给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。

如果数组元素个数小于 2,则返回 0。

示例1:

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

示例 2:

输入: [10]
输出: 0
解释: 数组元素个数小于 2,因此返回 0。

说明:

  • 你可以假设数组中所有元素都是非负整数,且数值在 32 位有符号整数范围内。
  • 请尝试在线性时间复杂度和空间复杂度的条件下解决此问题。

sort暴力求解

思路 由题意我们得知,需要求出排序后的最大间距,那么我们就根据题意来做

具体实现方式:

  • 首先要把数组处理成排序的数组,这里直接用sort来进行排序
  • 接来下需要比较相邻两个之间的差距,所以我们让当前元素与上个元素进行比较
  • 初始化pre为第一个元素
  • 遍历整个数组,每次用当前元素减去上一个元素pre作差,因为是升序排序的数组,所以作差已定位正值,并且与max(初始化为0)进行比较,用Math.max来区较大的差来保存在max中 最后直接返回max即可
var maximumGap = function(nums) {
    nums.sort((a,b)=>a-b)
    var pre = nums[0]
    var max = 0
    for(var i=1;i<nums.length;i++){
        max = Math.max(nums[i]-pre,max)
        pre = nums[i]
    }
    return max;
};

基数排序

思路 由题可得我们需要对数组先进行排序,这里我们使用基数排序

具体步骤:

  • 处理边界条件,数组长度小于2直接返回0
  • 对于所有元素的各位进行分组,分别放入cnt中,从0到9,每分配一个就统计总数++
  • 接着处理cnt前缀和,以此来得到cnt中的i在原数组的具体下标位置信息
  • 从后遍历nums,并且通过digit找到cnt中的位置信息,因为cnt中是从数量1开始计数的,反映到数组下标就需要-1,这样来重新排序原数组
  • 重复以上步骤直到maxVal<exp就能得到一个有序的数组了
  • 进行最大差ret的比较 最后返回ret即可
var maximumGap = function(nums) {
    const n = nums.length;
    if (n < 2) {
        return 0;
    }
    let exp = 1;
    const buf = new Array(n).fill(0);
    const maxVal = Math.max(...nums);

    while (maxVal >= exp) {
        const cnt = new Array(10).fill(0);
        for (let i = 0; i < n; i++) {
            let digit = Math.floor(nums[i] / exp) % 10;
            cnt[digit]++;
        }
        for (let i = 1; i < 10; i++) {
            cnt[i] += cnt[i - 1];
        }
        for (let i = n - 1; i >= 0; i--) {
            let digit = Math.floor(nums[i] / exp) % 10;
            buf[cnt[digit] - 1] = nums[i];
            cnt[digit]--;
        }
        nums.splice(0, n, ...buf);
        exp *= 10;
    }
    
    let ret = 0;
    for (let i = 1; i < n; i++) {
        ret = Math.max(ret, nums[i] - nums[i - 1]);
    }
    return ret;
};