题目
给定一个无序的数组 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 <= 105
0 <= nums[i] <= 109
题解
解题思路
可以先对数组进行排序,排好序后就很容易可以得到最大的差值了。但是题目中明确说明了要实现一个「线性时间」内运行并使用「线性额外空间」的算法,所以使用快速排序、归并排序等常见排序均不能满足,时间复杂度为 O(n logn),都是非线性的。需要使用基数排序,基数排序 可以在的 O(n) 的时间复杂度内完成排序。
基数排序
主要思想:
将元素按照数字的每一位进行多轮的分配和收集,从最低位开始,按当前位的值进行排序,直到完成最高位处理后,即可得到一个有序的数组,该算法是一个稳定的排序算法,主要适用于整数和字符串的排序(需统一位数)。
基数排序
的主要步骤:
从最低位开始,基于各个位对元素进行以下操作,直到完成最高一位的处理,即完成了数组的排序。这里假设正在处理的为第 i 位。
-
统计在第 i 位上各取值对应的元素数
-
基于上一步的结果得到在第 i 位上各取值对应元素在本轮排序结果数组中的下标范围
-
将数组元素逐一按照上一步得到的下标分布进行调整位置,当然这不是在原数组中操作,需要借助一个临时数组 buf 存放结果。
-
把 buf 数组拷贝回原数组
代码
class Solution {
public int maximumGap(int[] nums) {
int n = nums.length;
if (n < 2) {
return 0;
}
int exp = 1;
int max = Arrays.stream(nums).max().getAsInt();
int[] buf = new int[n];
while(max >= exp) {
int[] counts = new int[10];
// 统计所有元素在 exp 对应位上值的分布
for (int i = 0; i < n; i++) {
int x = (nums[i] / exp) % 10;
counts[x]++;
}
// 统计本轮排序在当前位各取值对应的元素下标情况
// 例如 counts[0] = 2, counts[1] = 5,说明当前位为 0 的元素将排在 0 ~ 1,为 1 的排在 2 ~ 4
for (int i = 1; i < counts.length; i++) {
counts[i] += counts[i - 1];
}
// 将数组按照前面得到的 counts 中的分布进行整理
// 从后往前处理是为了保证排序稳定性
for (int i = n - 1; i >= 0; i--) {
int x = (nums[i] / exp) % 10;
buf[counts[x] - 1] = nums[i];
counts[x]--;
}
System.arraycopy(buf, 0, nums, 0, n);
// 接下来处理更高一位
exp *= 10;
}
// 从排好序的数组中获取到答案
int res = 0;
for (int i = 1; i < n; i++) {
if (nums[i] - nums[i - 1] > res) {
res = nums[i] - nums[i - 1];
}
}
return res;
}
}
复杂度分析
- 时间复杂度:O(n)
n 为数组的长度。 - 空间复杂度:O(n)
优质项目推荐
推荐一个可用于练手、毕业设计参考、增加简历亮点的项目。
lemon-puls/txing-oj-backend: Txing 在线编程学习平台,集在线做题、编程竞赛、即时通讯、文章创作、视频教程、技术论坛为一体
公众号
有兴趣可以关注公众号一起学习更多的干货哈!