[LeetCode] 164. Maximum Gap

Given an unsorted array, find the maximum difference between the successive elements in its sorted form.

Return 0 if the array contains less than 2 elements.

Example 1:

Input: [3,6,9,1]
Output: 3
Explanation: The sorted form of the array is [1,3,6,9], either
             (3,6) or (6,9) has the maximum difference 3.

Example 2:

Input: [10]
Output: 0
Explanation: The array contains less than 2 elements, therefore return 0.

Note:

  • You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.
  • Try to solve it in linear time/space.

最大间距。

题意是给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。如果数组元素个数小于 2,则返回 0。

这道题由于要求是在线性时间和空间内解决,所以思路是桶排序。桶排序的具体做法如下,这里的桶排序跟其他题目涉及到的桶排序/计数排序是不同的,这里我们是试图要把元素放入每一个桶但是又想确保有一个bucket是空的。这个空的bucket的前一个bucket里的最大值和后一个bucket里的最小值的差值就是要求的最大差值。比如我们有 N 个元素,我们可以试图给 N + 1 个bucket,那么一定有一个bucket是空的。这个推论类似于抽屉原理。我们可以找这个空的bucket的左右两个邻居bucket来得到这个最大差值。

所以具体的做法是,遍历input数组,得到数组中的最大值max和最小值min,此时我们可以得到桶的size = (int) Math.ceil((double) (max - min) / (len - 1))。这个公式我暂时不知道怎么推导,暂且当做结论记住。同时我们还需要两个长度为 len - 1 的数组来分别记录每个bucket里的最大值和最小值。

再次遍历input数组,如果遇到min和max就跳过,因为他们是第一个bucket的最小值和最后一个bucket的最大值,第一个bucket左边没有bucket,最后一个bucket的右边也没有bucket,所以他们没有办法参与到res的计算中,可以跳过。桶的size得到之后,对于每一个元素,我们通过这个公式就知道应该把他放入哪个bucket了。放入之后同时记得更新这个桶内的最大值和最小值。

int bucket = (num - min) / gap;

最后遍历桶的最大值数组和最小值数组,记得单独处理min和第一个桶子里的最小值的差值以及max和最后一个桶子里的最大值的差值计算。

时间O(n) - required

空间O(n)

Java实现

 1 class Solution {
 2     public int maximumGap(int[] nums) {
 3         // corner case
 4         if (nums == null || nums.length < 2) {
 5             return 0;
 6         }
 7         // normal case
 8         int len = nums.length;
 9         int min = nums[0];
10         int max = nums[0];
11         for (int num : nums) {
12             min = Math.min(min, num);
13             max = Math.max(max, num);
14         }
15         // bucket size
16         int gap = (int) Math.ceil((double) (max - min) / (len - 1));
17         int[] bucketMin = new int[len - 1];
18         int[] bucketMax = new int[len - 1];
19         Arrays.fill(bucketMin, Integer.MAX_VALUE);
20         Arrays.fill(bucketMax, Integer.MIN_VALUE);
21         for (int num : nums) {
22             // 跳过最大值和最小值是因为最大值是最后一个bucket的上限,他的右边没有bucket了
23             // 最小值是第一个bucket的下限,他的左边没有bucket了
24             // 所以实际是没法参与到res的计算中的,所以直接就不放了
25             if (num == min || num == max) {
26                 continue;
27             }
28             int bucket = (num - min) / gap;
29             bucketMin[bucket] = Math.min(num, bucketMin[bucket]);
30             bucketMax[bucket] = Math.max(num, bucketMax[bucket]);
31         }
32 
33         int res = 0;
34         int pre = min;
35         for (int i = 0; i < len - 1; i++) {
36             if (bucketMin[i] == Integer.MAX_VALUE && bucketMax[i] == Integer.MIN_VALUE) {
37                 continue;
38             }
39             res = Math.max(res, bucketMin[i] - pre);
40             pre = bucketMax[i];
41         }
42         res = Math.max(res, max - pre);
43         return res;
44     }
45 }

 

LeetCode 题目总结

posted @ 2020-09-30 07:53  CNoodle  阅读(206)  评论(0编辑  收藏  举报