【Lintcode】 maximum gap

class Solution {
public:
    /**
     * @param nums: a vector of integers
     * @return: the maximum difference
     */
    int maximumGap(vector<int> nums) {
        // write your code here
        int N = nums.size();
        if (N < 2) return 0;
        int m1 = *min_element(nums.begin(),nums.end());
        int m2 = *max_element(nums.begin(),nums.end());
        if (m1 == m2) return 0;
        
        int M = static_cast<int>(sqrt(N)) + 1;
        vector<int> interMin = vector<int>(M,INT_MAX);
        vector<int> interMax = vector<int>(M,INT_MIN);
        int W = (m2 - m1)/M + 1;
        
        auto a = vector<vector<int>>(M,vector<int>{});
        
        for (auto x : nums) 
        {
            auto index = (x - m1)/W;
            a[index].push_back(x);
            interMin[index] = min(interMin[index],x);
            interMax[index] = max(interMax[index],x);
        }
        
        int ret = 0;
        for (auto x : a) ret = max(ret,maximumGap(x));
        int last = INT_MIN;
        for (int i = 0;i<M;i++)
        {
            if (!a[i].size()) continue;
            if (last != INT_MIN)
            ret = max(ret,interMin[i] - last);
            last = interMax[i];
        }
        return ret;
    }
};

自己想了个蠢蠢的递归,是不是O(N)有待商榷

后来看了leetcode上的解答(顺便吐槽一下,这两个题库名字这么像),才知道

N个数有(N-1)个GAP,这些gap一共长m2-m1

平均长度是(double)(m2-m1)/(N-1), 因为CAP大小是整数, 所以最大的GAP比这个平均数大

所以最大GAP的最小值是W=(m2-m1-1)/(N-1) + 1 (注意排除m1=m2的情况)

这个思想是在YYJ老师的组合数学的课上学到的,很好用

另外这里有个小技巧,就是这个gap的表达式把(N-1)是不是整除(m2-m1) 的情况都包含了

这样我保证一个区间里面有W个元素,这个区间里面的最大GAP也是W-1

把x分到第(x-m1)/W个区间,m1分到第0个,m2分到第(m2-m1)/W个区间

//那么m2会不会分到m1的区间呢?不会,因为这样最大的GAP<=W-1与最大GAP最小是W矛盾。

一共有M= (m2-m1)/W+1个区间

这样我只要记录每个区间的最小值和最大值就行了

后来在leetcode上又码了一遍这个算法

class Solution {
public:
    int maximumGap(vector<int>& nums) {
        int N = nums.size();
        if (N < 2) return 0;
        int m1 = *min_element(nums.begin(),nums.end());
        int m2 = *max_element(nums.begin(),nums.end());
        if (m1 == m2) return 0;
        int W = (m2 - m1 - 1)/(N - 1) + 1; //W = minGap
        
        int M = (m2 - m1)/W + 1;
        auto v = vector<bool>(M,false);
        vector<int> interMin = vector<int>(M,INT_MAX);
        vector<int> interMax = vector<int>(M,INT_MIN);
        for (auto x : nums) 
        {
            auto index = (x - m1)/W;
            v[index] = true;
            interMin[index] = min(interMin[index],x);
            interMax[index] = max(interMax[index],x);
        }
        
        int ret = 0;
        int last = INT_MIN;
        for (int i = 0;i < M;i++)
        {
            if (!v[i]) continue;
            if (last >= 0)
            ret = max(ret,interMin[i] - last);
            last = interMax[i];
        }
        
        return ret;
    }
};

 

posted @ 2016-03-02 16:13  syb3181  阅读(243)  评论(0编辑  收藏  举报