Return 0 if the array contains less than 2 elements.
You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.
Example 1:
Input: [1, 9, 2, 5]
Output: 4
Explanation: The sorted form is [1, 2, 5, 9], and the maximum gap is between 5 and 9.
Example 2:
Input: [1]
Output: 0
Explanation: The array contains less than 2 elements.
Sort is easy but will cost O(nlogn) time. Try to solve it in linear time and space.
思路:
很多人用基数排序(桶排序)做这道题目, 时间复杂度接近线性, 当然比基于比较的快速排序等一众 O(nlogn) 的算法要优秀一些, 但是这道题可以有更巧妙的方法.
首先我们定义 maxNum 和 minNum 表示这个数组的最大/最小元素, N 表示这个数组元素的个数. 那么这个数组一共有 N - 1 个间距.
这 N - 1 个间距的平均值就是 avgGap = (maxNum - minNum) / (N - 1), 这个平均值也是答案的最小值. 因为这 N 个元素平均分配时, 最大的间距最小.
然后我们对这 N 个元素分类, 分类依据就是这个元素与 minNum 的间距是 avgGap 的多少倍. 为什么这样分类呢? 因为这样分类, 同一组内的元素的间距必然不会是最大间距.
这时我们要找的最大间距处于组与组之间, 即某一组里最小的元素与它上一组的最大的元素的间距的最大值. 因此, 我们只需要维护每一组里最小与最大的元素即可.
设定 maxNums 和 minNums 数组, maxNums[i] 表示原数组中与 minNum 的差为 avgGap 的 i 倍(向下取整)的最大的元素, 同理 minNums[i] 表示相同含义下的最小的元素.
然后我们遍历 maxNums, minNums, 将第 i 组的最小值 minNums[i] 与第 i - 1 组的最大值 maxNums[i - 1] 做差, 维护最大值就可以public class Solution
public class Solution { /** * @param nums: an array of integers * @return: the maximun difference */ class Block { public int min = Integer.MAX_VALUE; public int max = Integer.MIN_VALUE; } /** * @param nums: an array of integers * @return: the maximun difference */ public int maximumGap(int[] nums) { if (nums == null || nums.length < 2) { return 0; } int min = nums[0], max = nums[0]; for (int num : nums) { min = Math.min(num, min); max = Math.max(num, max); } if (max == min) { return 0; } int N = nums.length; Block[] blocks = new Block[N]; for (int i = 0; i < N; i++) { blocks[i] = new Block(); } int avgGap = (int) Math.ceil((double) (max - min) / (nums.length - 1)); for (int num : nums) { if (num == min || num == max) { continue; } int pos = (num - min) / avgGap; blocks[pos].min = Math.min(num, blocks[pos].min); blocks[pos].max = Math.max(num, blocks[pos].max); } int maxGap = 0; int lastMax = min; for (int i = 0; i < N; i++) { if (blocks[i].min == Integer.MAX_VALUE || blocks[i].max == Integer.MIN_VALUE) { continue ; } maxGap = Math.max(maxGap, blocks[i].min - lastMax); lastMax = blocks[i].max; } maxGap = Math.max(maxGap, max - lastMax); return maxGap; } }
原文:https://www.cnblogs.com/FLAGyuri/p/12078501.html