「这是我参与2022首次更文挑战的第33天,活动详情查看:2022首次更文挑战」
题目
给定一个无序的数组 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次方
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/ma… 著作权归领扣网络所有。
解题思路
因为题目对时间、空间复杂度有要求,所以不能用快速、归并排序。这里使用基数排序,基数排序是稳定的排序,并且可以保证时间和空间复杂度是O(n)。
处理过程如下:
- 首先对个位数字进行计数;
- 再对计数结果计算前缀和,得到0-9存放的最大下标;
- 将数字从右往左根据下标写入临时数组中;
- 将临时数组中的元素写回原数组中;
- 重复高一位做以上操作;
代码实现
var maximumGap = function(nums) {
//数组中只有一个元素或没有元素时没有最大间距
if (nums.length < 2) return 0
const len = nums.length
const temp = new Array(len)
const max = Math.max(... nums)
let exp = 1
//如果最大数字大于等于第 exp,则对 exp 为进行排序
while(max >= exp) {
//声明计数结果数组,并将每个元素初始化为 0
const cnt = new Array(10).fill(0)
//对 exp 位进行计数,将结果放在 cnt 数组中
for (const x of nums) {
//计算 exp 位的值
const digit = Math.floor(x / exp) % 10
cnt[digit]++
}
//计算前缀和
for (let i = 1; i < 10; i++) cnt[i] += cnt[i - 1]
//将 exp 位排序的结果放入 temp 数组中,从后往前放入
for (let i = len - 1; i >= 0; i--) {
//计算 exp 位的值
const digit = Math.floor(nums[i] / exp) % 10
//将 nums[i] 放入到 cnt[digit] 位上,并且 cnt[digit] 减1
temp[--cnt[digit]] = nums[i]
}
//将 temp 数组中已排序的元素更新到 nums 数组中
nums = [...temp]
//对高一位进行计数排序操作
exp *= 10
}
let ans = 0
//遍历排序后的数组,计算相邻元素之间的差,取其中最大的差
for (let i = 1; i < len; i ++) {
ans = Math.max(ans, nums[i] - nums[i - 1])
}
return ans
};
如有错误欢迎指出,欢迎一起讨论!