Sunday, January 11, 2015

LeetCode 164: 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.
public class Solution {
    public int maximumGap(int[] num) {
        // Suppose there are N elements and they range from A to B.
        // Then the maximum gap will be no smaller than ceiling[(B - A) / (N - 1)]
        // Let the length of a bucket to be len = ceiling[(B - A) / (N - 1)]
        // Then we will have at most num = (B - A) / len + 1 of bucket (num = (B - A) / len + 1 = N)
        
        // for any number K in the array, we can easily find out which bucket it belongs by calculating loc = (K - A) / len
        // and therefore maintain the maximum and minimum elements in each bucket.
        // Since the maximum difference between elements in the same buckets will be at most len - 1
        // So the final answer will not be taken from two elements in the same buckets.
        // For each non-empty buckets p, find the next non-empty buckets q
        // Then q.min - p.max could be the potential answer to the question. Return the maximum of all those values.        
        int n = num.length;
        
        if (n < 2)
            return 0;
            
        // Find the max and min value in the array
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
        
        for (int value: num)
        {
            min = Math.min(min, value);
            max = Math.max(max, value);
        }
        
        int gap = (int)Math.ceil((double)(max-min) / (n-1)); // maxGap should be no smaller than gap (gap = len)
        
        int[] minNums = new int[n-1]; // Store the min value in the bucket
        int[] maxNums = new int[n-1]; // Store the max value in the bucket
        
        Arrays.fill(minNums, Integer.MAX_VALUE);
        Arrays.fill(maxNums, Integer.MIN_VALUE);
        
        for (int value : num)
        {
            if (value != min && value != max)
            {
                // min and max will be considered as two special buckets
                int i = (value - min) / gap; // Calc the bucket index
                minNums[i] = Math.min(minNums[i], value);
                maxNums[i] = Math.max(maxNums[i], value);
            }
        }
        
        // Scan the buckets for the max gap
        int maxGap = Integer.MIN_VALUE;
        int prevMax = min; // last non-empty bucket max value
        
        for (int i = 0; i < num.length - 1; ++i)
        {
            if (minNums[i]!=Integer.MAX_VALUE && maxNums[i]!=Integer.MIN_VALUE)
            {
                // non-empty bucket
                maxGap = Math.max(maxGap, minNums[i] - prevMax);
                prevMax = maxNums[i];
            }
        }
        
        maxGap = Math.max(maxGap, max - prevMax); 
                
        return maxGap;
    }
}

No comments:

Post a Comment