设数组大小为n。第一遍扫描,记录数组中最小以及最大的数,则数组中所有的数都处在这两个数所限定的区间内。把这个区间平均分成n份,即n个桶。
第二次扫描将数组中的数一一映射到n个桶中的某一个,同时更新每个桶中的最大值和最小值。
第三次扫描,检测相邻的两个非空桶最靠近的两个数的差值得出结果,因为最大差值不可能出现在同一个桶中(一共n个桶,n个数,若某个桶中的数超过1个,则肯定有空桶,而空桶的大小比桶中任意两个数的差值大)。
一共三次扫描,时间复杂度O(n)。
- /*2015.9.7cyq*/
- #include <iostream>
- #include <vector>
- #include <set>
- #include <algorithm>
- using namespace std;
- //直接使用STL的sort排序,复杂度O(nlogn)
- class Solution1{
- public:
- int maximumGap(vector<int>& nums) {
- if(nums.size()<2) return 0;
- sort(nums.begin(),nums.end());
- int maxGap=0;
- for(int i=1;i<nums.size();i++)
- if(nums[i]-nums[i-1]>maxGap)
- maxGap=nums[i]-nums[i-1];
- return maxGap;
- }
- };
- //桶排序,复杂度O(n)
- class Solution{
- public:
- int maximumGap(vector<int>& nums) {
- if(nums.size()<2) return 0;
- int up=nums[0];//数组中最大的数
- int down=nums[0];//数组中最小的数
- for(int i=1;i<nums.size();i++){
- if(nums[i]>up)
- up=nums[i];
- else if(nums[i]<down)
- down=nums[i];
- }
- int len=up-down;
- if(len<=1)
- return len;
- int n=nums.size();//桶的个数
- vector<int> bucketMax(n,INT_MIN);//记录桶中最大的数
- vector<int> bucketMin(n,INT_MAX);//记录桶中最小的数
- for(int i=0;i<n;i++){
- int index=(double)(nums[i]-down)/len*(n-1);//映射到n个桶中的一个,先除再乘避免溢出
- bucketMax[index]=max(bucketMax[index],nums[i]);
- bucketMin[index]=min(bucketMin[index],nums[i]);
- }
- int gap=0;
- int pre=bucketMax[0];//0号桶肯定不是空桶,下界在里面
- for(int i=1;i<n;i++){
- if(bucketMax[i]!=INT_MIN){//i号桶不是空桶
- gap=max(gap,bucketMin[i]-pre);
- pre=bucketMax[i];
- }
- }
- return gap;
- }
- };
- int main(){
- int a[]={1,7,5,9,9,2};
- vector<int> ivec(a,a+sizeof(a)/sizeof(int));
- Solution1 solu;
- cout<<solu.maximumGap(ivec);
- return 0;
- }