持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第21天,点击查看活动详情
给定一个无序的数组 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^50 <= 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;
};