[路飞]_leetcode-164-最大间距

95 阅读2分钟

题目描述

[题目地址]

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

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

示例 1:

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

示例 2:

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

说明:

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

解题思路

本题给出了信息:

  • 数组中所有元素都是非负整数
  • 数值在 32 位有符号整数范围内

给出了要求:

  • 在线性时间复杂度和空间复杂度的条件下解决此问题

因为本题要求的是数组排序之后的相邻元素之间的最大差值,所以我们要对输入数组进行排序。
而本题要求在线性时间复杂度和空间复杂度的条件下解决此问题,就说明我们算法的时间复杂度和空间复杂度都应该是 O(n) 的,而排序算法中时间复杂度为 O(n) 的我们可以想到 计数排序基数排序。而这里题目给出的信息,数值是在 32 位有符号整数范围内,所以如果使用 计数排序,开的计数数组会很大,所以我们可以采用 基数排序 对输入数组进行排序,然后遍历排序后的结果,获取最大差值即可。

代码实现

var maximumGap = function(nums) {
    let cnt = new Array(65536).fill(0);//记录下标和
    let temp = new Array(nums.length);//临时数组
    for(let i = 0; i < nums.length; i++){
        cnt[nums[i] & 0xffff] += 1;
    }
    // 记录每一个下标前缀和
    for(let i = 1; i < 65536; i++){
        cnt[i] += cnt[i - 1];
    }
    // 把数字按照记录的下标,放到临时数组中
    for(let i = nums.length -1; i >= 0 ; i--){
        // 重新赋值
        temp[--cnt[nums[i] & 0xffff]] = nums[i]; 
    }
    // 重置
    cnt = new Array(65536).fill(0);
    // 把数字按着区间范围16次方~32次方
    for(let i = 0; i < temp.length ; i++){
        // 将每一个下标
        cnt[(temp[i] & 0xffff0000) >> 16] += 1;
    }
    for(let i = 1; i < 65536; i++){
        cnt[i] += cnt[i-1];
    }
    for(let i = nums.length -1 ; i >= 0; i--){
        nums[--cnt[(temp[i] & 0xffff0000) >> 16]] = temp[i];
    }
    let ans = [];
    for(let i = 1; i < nums.length; i++){
        ans = Math.max(ans,nums[i] - nums[i - 1]);
    }
    return ans;
};

至此我们就完成了leetcode-164-最大间距