「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」
题目
给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。
如果数组元素个数小于 2,则返回 0。
示例1
输入: [3,6,9,1]
输出: 3
解释: 排序后的数组是 [1,3,6,9] , 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。
示例2
输入: [10]
输出: 0
解释: 数组元素个数小于 2,因此返回 0。
题解
暴力全排序
找到排序后相邻元素之间最大的差值。最容易想到的思路就是将数组整个排序,根据排序后的结果枚举数组,逐一对比相邻元素值。变量记录相邻元素之差的最大值即可;具体代码如下:
时间复杂度:全排序需要的时间复杂度为O(nlogN),枚举需要的时间复杂度为O(n);所以总体时间复杂度为O(nlogN)
代码
var maximumGap = function (nums) {
if (nums.length < 2) return 0
nums.sort((a, b) => a - b)
let max = 0
for (let i = 1; i < nums.length; i++) {
max = Math.max(max, nums[i] - nums[i - 1])
}
return max
}
进阶要求
- 你可以假设数组中所有元素都是非负整数,且数值在 32 位有符号整数范围内
- 请尝试在线性时间复杂度和空间复杂度的条件下解决此问题
桶排序
假设现在有数组 nums = [3,6,9,1];
- 数组长度为len=4
- 数组最大值max = 9
- 数组最小值min = 1
- 数组最大间距为 max - min = 8
- 讲最大间距8均分到len-1份,得到每份间距space = 8/3 (向下取整) = 2;
- 每份间距为2,长度为8的间距需要 8/2+1 = 5个桶
- 五个桶分别是[1,2],[3,4],[5,6],[7,8],[9,10];
- 将数据放入桶中,有数据放数据,没数据设置为0;
- 得到数据为[ [ 1, 1 ], [ 3, 3 ], [ 6, 6 ], [ 0, 0 ], [ 9, 9 ] ];
- 解释:桶1的最大数据为1,最小数据为1,
- 桶2、3类似
- 桶4表示[7,8]这个区间,因为数组没有7、8这两个值,所以此处是空桶
- 桶5与桶1、2、3类似
- 五个桶,每个桶可以装2个数据(间距是2);一共可以装10个数据,但是数组中最大值与最小值之差是8;也就是说必然最少有一个桶是空的;
这句话比较关键,需要理解 - 将数据放入桶中,必然有一个桶中最大值与下一个非空桶最小值在排序数据相邻;
关键 - 又因为一定存在空桶,必然够空桶左右两个非空桶内数据的差值大于桶内各个数据差值
- 根据上述思路编辑代码如下
桶排序代码
var maximumGap = function (nums) {
const len = nums.length;
if (len < 2) return 0;
let max = -Infinity;
let min = Infinity;
for (let i = 0; i < len; i++) {
max = Math.max(max, nums[i]);
min = Math.min(min, nums[i]);
}
const space = Math.max(1, Math.floor((max - min) / (len - 1)));
const bucketLength = Math.floor((max - min) / space) + 1;
const bucket = [];
for (let i = 0; i < bucketLength; ++i) {
bucket[i] = Array(2).fill(0);
}
for (let i = 0; i < len; i++) {
const idx = Math.floor((nums[i] - min) / space);
if (bucket[idx][0] === 0) {
bucket[idx][0] = bucket[idx][1] = nums[i];
} else {
bucket[idx][0] = Math.min(bucket[idx][0], nums[i]);
bucket[idx][1] = Math.max(bucket[idx][1], nums[i]);
}
}
let prev = null;
let result = 0;
for (let i = 0; i < bucketLength; i++) {
if (bucket[i][0] === 0) continue;
if (prev !== null) {
result = Math.max(result, bucket[i][0] - bucket[prev][1]);
}
prev = i;
}
return result;
};