LeetCode Maximum Gap

来源:互联网 发布:程序员面试着装 编辑:程序博客网 时间:2024/05/21 00:45

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)的时间和空间复杂度,显然不能使用quick sort,merge sort, heap sort这类基于比较的排序算法,因为是O(Nlog(N))的时间复杂度。于是我们考虑使用bukit sort,radix sort,counting sort的思路。这里给出基于bukit sort的解法。假设num数组中最大值和最小值为max和min,那么我们可以令每个桶的大小为bukitLength = Math.ceil((double) (max - min) / (double) (n-1)),我们定义(max -  min) / bukitLength  + 1个桶,就可以保证存下从min到max这个range内的所有值。注意其实我们也可以定义其他的桶大小,比如Math.ceil((double) (max - min) / (double) (n)), 但此时要注意防止出现最大元素的桶index越界的情况,我们可以多定义一个bukit。定义好桶之后,就可以根据元素大小放入桶中。注意max gap不可能存在于同一个桶的元素之间,因为同一个桶的元素之间个gap至多只能是bukitLength-1,如果max gap是某两个同一个桶中的元素,那么这些数的range一定比max - min要小,出现矛盾。所以,对于数组中的任意整数K,可以通过算式loc = (K - min) / bukitLength找出其桶的位置,然后维护每一个桶的最大值和最小值。对于每一个非空的桶p,找出下一个非空的桶q,则q.min - p.max可能就是备选答案。返回这些备选答案中最大的一个即可。在实现的过程中犯了一个不该犯的错误,没有注释掉测试输出语句,导致超时。输出语句显然是很费时的,以后要引以为戒。

AC Code

public class Solution {    public int maximumGap(int[] num) {        if(num ==  null || num.length < 2) return 0;        int n = num.length;        int max = Integer.MIN_VALUE;        int min = Integer.MAX_VALUE;        for(int i = 0; i < n; i++){            max = Math.max(max, num[i]);            min = Math.min(min, num[i]);        }        int range = max - min;        int bukitLength = (int)Math.ceil((double) range / (double) (n-1));        int bukitNum = range / bukitLength + 1;        //System.out.println("BukitLength and BukitNum " + bukitLength + " " + bukitNum);                ArrayList<Integer> bukitMax = new ArrayList<Integer>();        ArrayList<Integer> bukitMin = new ArrayList<Integer>();                for(int i = 0; i < bukitNum; i++){        bukitMax.add(Integer.MIN_VALUE);        bukitMin.add(Integer.MAX_VALUE);        }                 for(int i = 0; i < n; i++){            int bukitIndex = (num[i] - min) / bukitLength;             //if(bukitIndex == n) bukitIndex--; // use n-1 bukits could solve the index problem of the largest number            //System.out.println("i and bukitIndex: " + i + " " + bukitIndex);            //Just store the largest and minimum number;            bukitMax.set(bukitIndex, Math.max(num[i], bukitMax.get(bukitIndex)));            bukitMin.set(bukitIndex, Math.min(num[i], bukitMin.get(bukitIndex)));        }        int beforeMax = min;        int maxGap = Integer.MIN_VALUE;        for(int i = 0; i < bukitNum; i++){        if(bukitMax.get(i) == Integer.MIN_VALUE || bukitMin.get(i) == Integer.MAX_VALUE){//empty bukit        continue;        }        maxGap = Math.max(maxGap, bukitMin.get(i) - beforeMax);        beforeMax = bukitMax.get(i);        }        return maxGap;    }}



1 0