Maximum Gap

描述

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

Try to solve it in linear time/space.

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.

分析

这道题最直接的解法是,先排序,得到有序数组,然后相邻元素相减,找出差最大的,时间复杂度O(n log n)

然而本题要求O(n)时间,有没有O(n)的排序算法呢?桶排序、基数排序、计数排序。

解法1 桶排序

  1. // Maximum Gap
  2. // Bucket Sort
  3. // Time Complexity: O(n+k), Space Complexity: O(n+k)
  4. public class Solution {
  5. public int maximumGap(int[] nums) {
  6. if (nums.length < 2) return 0;
  7. bucketSort(nums);
  8. int maxDiff = Integer.MIN_VALUE;
  9. for (int i = 1; i < nums.length; ++i) {
  10. maxDiff = Math.max(maxDiff, nums[i] - nums[i - 1]);
  11. }
  12. return maxDiff;
  13. }
  14. private static void bucketSort(int[] nums) {
  15. if (nums.length < 2) return;
  16. int minValue = Integer.MAX_VALUE;
  17. int maxValue = Integer.MIN_VALUE;
  18. for (int i : nums) {
  19. minValue = Math.min(minValue, i);
  20. maxValue = Math.max(maxValue, i);
  21. }
  22. final int bucketSize = (maxValue - minValue) / nums.length + 1;
  23. final int bucketCount = (maxValue - minValue) / bucketSize + 1;
  24. final ArrayList<Integer>[] buckets = new ArrayList[bucketCount];
  25. for (int i = 0; i < buckets.length; ++i) {
  26. buckets[i] = new ArrayList<>();
  27. }
  28. for (int x : nums) {
  29. final int index = (x - minValue) / bucketSize;
  30. buckets[index].add(x);
  31. }
  32. for (final ArrayList<Integer> list : buckets) {
  33. Collections.sort(list);
  34. }
  35. int i = 0;
  36. for (final ArrayList<Integer> list : buckets) {
  37. for (int x : list) {
  38. nums[i++] = x;
  39. }
  40. }
  41. }
  42. }

解法2 基数排序

  1. // Maximum Gap
  2. // Radix Sort
  3. // Time Complexity: O(nd), Space Complexity: O(n+d)
  4. public class Solution {
  5. public int maximumGap(int[] nums) {
  6. if (nums.length < 2) return 0;
  7. radixSort(nums);
  8. int maxDiff = Integer.MIN_VALUE;
  9. for (int i = 1; i < nums.length; ++i) {
  10. maxDiff = Math.max(maxDiff, nums[i] - nums[i - 1]);
  11. }
  12. return maxDiff;
  13. }
  14. private static void radixSort(int[] nums) {
  15. int minValue = Integer.MAX_VALUE;
  16. int maxValue = Integer.MIN_VALUE;
  17. for (int i : nums) {
  18. minValue = Math.min(minValue, i);
  19. maxValue = Math.max(maxValue, i);
  20. }
  21. final int D = Integer.toString(maxValue - minValue).length();
  22. final ArrayList<Integer>[] buckets = new ArrayList[10];
  23. for (int i = 0; i < buckets.length; ++i) {
  24. buckets[i] = new ArrayList<>();
  25. }
  26. for (int i = 0; i < D; ++i) {
  27. for (int x : nums) {
  28. final int index = getDigit(x - minValue, i);
  29. final ArrayList<Integer> bucket = buckets[index];
  30. bucket.add(x);
  31. }
  32. int index = 0;
  33. for (ArrayList<Integer> bucket : buckets) {
  34. for (int x : bucket) {
  35. nums[index++] = x;
  36. }
  37. bucket.clear();
  38. }
  39. }
  40. }
  41. // get the i-th digit of n
  42. private static int getDigit(int n, int i) {
  43. for (int j = 0; j < i; ++j) {
  44. n /= 10;
  45. }
  46. return n % 10;
  47. }
  48. }

解法3 计数排序

计数排序本质上是一种特殊的桶排序,当桶的个数最大的时候,就是计数排序。

本题用计数排序会MLE。

  1. // Maximum Gap
  2. // Counting Sort
  3. // Time Complexity: O(n), Space Complexity: O(max-min)
  4. public class Solution {
  5. public int maximumGap(int[] nums) {
  6. if (nums.length < 2) return 0;
  7. countingSort(nums);
  8. int maxDiff = Integer.MIN_VALUE;
  9. for (int i = 1; i < nums.length; ++i) {
  10. maxDiff = Math.max(maxDiff, nums[i] - nums[i - 1]);
  11. }
  12. return maxDiff;
  13. }
  14. private static void countingSort(int[] nums) {
  15. int minValue = Integer.MAX_VALUE;
  16. int maxValue = Integer.MIN_VALUE;
  17. for (int i : nums) {
  18. minValue = Math.min(minValue, i);
  19. maxValue = Math.max(maxValue, i);
  20. }
  21. final int[] buckets = new int[maxValue - minValue + 1];
  22. for (int i : nums) {
  23. buckets[i - minValue]++;
  24. }
  25. for (int i = 0, index = 0; i < buckets.length; ++i) {
  26. Arrays.fill(nums, index, index + buckets[i], i + minValue);
  27. index += buckets[i];
  28. }
  29. }
  30. }

原文: https://soulmachine.gitbooks.io/algorithm-essentials/content/java/sorting/radix-sort/maximum-gap.html