最大间距

342 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情

164. 最大间距 - 力扣(LeetCode)

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

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 10^5
  • 0 <= nums[i] <= 10^9

思路

如果本题不要求 “线性时间” 内运行,求解非常简单,只需要先排序,在遍历求两数差的最大值即可,如解法一。

现在有时间要求,我们就需要选择一种合适的排序方法达到时间要求,基于桶排序的算法是排序算法中为数不多的满足要求的排序算法。设数组长度为n,数组最大值和最小值差为m,则排序后相邻数字间距最大值大于等于m/(n-1),记为d,我们将m划分为若干个大小为d - 1的桶,我们将数组中的元素都找到所属的桶,并维护桶内的最大值和最小值,由于排序后相邻数字间距最大值大于等于d,则元素间最大值一定不会出现在同一个桶内,一定在不同的桶内。遍历桶间最值差,就可以求解了,如解法二。

解法

解法一

/**
 * @param {number[]} nums
 * @return {number}
 */
var maximumGap = function (nums) {
  nums.sort((a, b) => a - b);
  let res = 0;
  for (i = 1; i < nums.length; i++) {
    res = Math.max(nums[i] - nums[i - 1], res);
  }
  return res;
};

解法二

/**
 * @param {number[]} nums
 * @return {number}
 */
var maximumGap = function (nums) {
  const n = nums.length;
  if (n === 1) return 0;
  const max = Math.max(...nums);
  const min = Math.min(...nums);
  const step = Math.max(1, ((max - min) / (n - 1)) | 0);
  const size = (((max - min) / step) | 0) + 1;
  const bucket = new Array(size).fill(0).map(() => new Array(2).fill(-1));
  for (let i = 0; i < n; i++) {
    let num = nums[i];
    let idx = ((num - min) / step) | 0;
    if (bucket[idx][0] === -1) {
      bucket[idx].fill(num);
    } else {
      bucket[idx][0] = Math.min(bucket[idx][0], num);
      bucket[idx][1] = Math.max(bucket[idx][1], num);
    }
  }
  let res = 0;
  let prev = bucket[0][1];
  for (let i = 1; i < size; i++) {
    if (bucket[i][0] !== -1) {
      res = Math.max(bucket[i][0] - prev, res);
      prev = bucket[i][1];
    }
  }
  return res;
};