給定一個無序的數組,找出數組在排序之后,相鄰元素之間最大的差值。
如果數組元素個數小于 2,則返回 0。
示例?1:
輸入: [3,6,9,1]
輸出: 3
解釋: 排序后的數組是 [1,3,6,9], 其中相鄰元素 (3,6) 和 (6,9) 之間都存在最大差值 3。
示例?2:
輸入: [10]
輸出: 0
解釋: 數組元素個數小于 2,因此返回 0。
說明:
你可以假設數組中所有元素都是非負整數,且數值在 32 位有符號整數范圍內。
請嘗試在線性時間復雜度和空間復雜度的條件下解決此問題。
思路:之前寫過,直接復制過來。
問題:
數組排序之后的相鄰數的最大差值;
嗯,你可以排序,然后找相鄰的最大差值。
但是你覺得這么簡單我寫他干啥。
最優解:時間復雜度O(N),空間O(1)
那我們開始說這種方法:
1)遍歷所有數,找到最小值和最大值:min和max
2)設數組長度為n,我們準備n+1個桶
3)把max放進最后一個桶里,min放到第一個桶里
4)每一個桶都負責放一個范圍內的數字,負責的范圍大小是(max-min)/n。
(比如長度為10,最小值為10,最大值為110,那么準備11個桶,第一個桶放[10,20)的數字,第二個桶放[20,30)的數字......)
重點來啦:因為有n+1個桶,有n個數字,我們就發現了一個問題:必定會有空的桶
為什么我們一定要有空的桶呢?
這樣我們就可以做到:桶內的相鄰數字的差,一定沒有不同桶之間的數字的差大
有了這個結論我們可以做什么呢?
其實找相鄰桶和桶之間的差就好啦,桶內的那些情況根本不用關心
想到這里,我們發現桶里根本不用關心到底有幾個數,他們的差是多少,只要記錄每個桶的最大值最小值即可。
?
最后一點小問題啦:對于一個數num,他應該放在哪個桶,最好推個公式吧?
它應該被放在(num-min)*len/(max-min)這個桶里。也不難推。
最后就是寫代碼啦。
class Solution {public int maximumGap(int[] nums) {if (nums == null || nums.length < 2) {return 0;}int len = nums.length;int min = Integer.MAX_VALUE;int max = Integer.MIN_VALUE;for (int i = 0; i < len; i++) {min = Math.min(min, nums[i]);max = Math.max(max, nums[i]);}if (min == max) {return 0;}boolean[] hasNum = new boolean[len + 1];//記錄是否空int[] maxs = new int[len + 1];//桶內最大值int[] mins = new int[len + 1];//桶內最小值int bid = 0;//放入桶中for (int i = 0; i < len; i++) {bid = bucket(nums[i], len, min, max);mins[bid] = hasNum[bid] ? Math.min(mins[bid], nums[i]) : nums[i];maxs[bid] = hasNum[bid] ? Math.max(maxs[bid], nums[i]) : nums[i];hasNum[bid] = true;}int res = 0;int lastMax = maxs[0];int i = 1;//相鄰桶求最大差值for (; i <= len; i++) {if (hasNum[i]) {res = Math.max(res, mins[i] - lastMax);lastMax = maxs[i];}}return res;}public int bucket(long num, long len, long min, long max) {return (int) ((num - min) * len / (max - min));}
}
?