LC164. Maximum Gap

O(n) sort

Posted by freeCookie🍪 on January 9, 2017

LC164. 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.

此题排序可做。此题要求线性时间空间排序, 那也就是桶排序和基数排序了,虽然知道复杂度但是对于具体实现不是很熟。

Bucket sort 桶排序

wiki

Bucket sort with code

中文

Bucket sort works as follows:

  1. Set up an array of initially empty “buckets”.
  2. Scatter: Go over the original array, putting each object in its bucket.
  3. Sort each non-empty bucket.
  4. Gather: Visit the buckets in order and put all elements back into the original array.

Pseudocode:

function bucketSort(array, n) is
  buckets ← new array of n empty lists
  for i = 0 to (length(array)-1) do
    insert array[i] into buckets[msbits(array[i], k)]
  for i = 0 to n - 1 do
    nextSort(buckets[i]);
  return the concatenation of buckets[0], ...., buckets[n-1]

保证桶中元素的顺序放入和取出,桶排序是stable的。

Bucket solution:

Bucket sort solution

中文

O(n) time and O(n) space.

public class Solution {
    public int maximumGap(int[] nums) {
        // bucket sort, for num in nums, max_gap(which is max - min) >= (max - min)/length-1
        // so let size of bucket = ceiling((max - min)/length-1)
        // so number of bucket <= max_gap/size + 1(<= nums.length), which ensures the result must be in two different bucket
        // we keep min and max in each bucket, the result is the max value of successive bucket difference
        // saying next_bucket.min-cur_bucket.max
        if(nums == null || nums.length < 2) return 0;
        int max = nums[0], min = nums[0];
        for(int n: nums){
            if(n > max) max = n;
            if(n < min) min = n;
        }
        // if all same number
        if(max == min)  return 0;
        int bsize = (int)Math.ceil((double)(max - min)/(nums.length - 1));
        int[] bmin = new int[nums.length];
        int[] bmax = new int[nums.length];
        Arrays.fill(bmin, Integer.MAX_VALUE);
        Arrays.fill(bmax, Integer.MIN_VALUE);
        for(int n: nums){
            int b = (n - min)/bsize;
            bmin[b] = Math.min(n, bmin[b]);
            bmax[b] = Math.max(n, bmax[b]);
        }
        int res = Integer.MIN_VALUE;
        int pre = min;
        for(int i = 0; i < nums.length; i++){
            // empty bucket
            if(bmin[i] == Integer.MAX_VALUE && bmax[i] == Integer.MIN_VALUE) continue;
            res = Math.max(res, bmin[i] - pre);
            pre = bmax[i];
        }
        res = Math.max(res, max - pre);
        return res;
    }
}

⚠️: min == max?

Radix sort 基数排序

wiki

Radix sort with code

LSD - Visualization

  • MSD: Most Significant Digit first
  • LSD: Least Significant Digit first

一般而言用LSD比较多一些, stable.

Radix solution:

Radix sort solution

利用10base LSD的基数排序, 然后比较相邻两数之差。

O(n) time and O(n) space.

public class Solution {
    public int maximumGap(int[] nums) {
      // radix sort, after sort compare each nums[i] - nums[i-1]
      // use 10 base, and longest length is 2^31 -> 10 digits
      if(nums == null || nums.length < 2)   return 0;
      int max = nums[0];
      for(int n: nums){
          if(n > max)   max = n;
      } // for n
      int[] copy = new int[nums.length];
      int d = 1; // LSD
      // using > instead of != will improve time for 2ms
      while(max/d > 0){
          int[] count = new int[10];
          for(int n: nums){
              count[(n/d)%10]++;
          }
          for(int i = 0; i < 9; i++){
              count[i+1] += count[i];
          }
          for(int i = nums.length - 1; i >= 0; i--){
              copy[--count[(nums[i]/d)%10]] = nums[i];
          }
          for(int i = 0; i < nums.length; i++){
              nums[i] = copy[i];
          }
          d *= 10;
      }
      max = Integer.MIN_VALUE;
      for(int i = 0; i < nums.length - 1; i++){
          max = Math.max(max, nums[i+1] - nums[i]);
      }
      return max;
    }
}