LintCode 400: Maximum Gap (bucket sort经典题!)

  1. Maximum Gap

Given an unsorted array, find the maximum difference between the successive elements in its sorted form.

Return 0 if the array contains less than 2 elements.

Example
Given [1, 9, 2, 5], the sorted form of it is [1, 2, 5, 9], the maximum gap is between 5 and 9 = 4.

Challenge
Sort is easy but will cost O(nlogn) time. Try to solve it in linear time and space.

Notice
You may assume all elements in the array are non-negative integers and fit in the 32-bit signed integer range.

解法1:bucket sorting
这题我想了半天,什么双指针,单调栈,DP都想了,最后觉得如果要时间复杂度和空间复杂度都是O(n)的话只能用类似bucket sort之类的方法。
首先是找到min和max,然后将其分成k份。这个k有讲究,不能超过n,但是也不能小于maxV-minV。所以取min(n, maxV-minV)。假如maxV-minV很小,则所有元素都挤在几个数上,那么最多也只能有maxV-minV个buckets。
然后我们分析一下就可以知道,相邻元素间隔最大值只可能是某个bucket的最大元素和下一个bucket的最小元素。那么为什么不可能是某个bucket里面的两个元素呢?因为我们将n个元素分到<=n个buckets里面,所以某个bucket最多分到一个元素!
那么可不可以分maxV-minV+1个buckets呢?可能可以,没有试。

注意:

  1. 特殊情况:
    a. 所有元素均相同 [1,1,1,1,1,1,1],此时返回0即可。
    b. 最大元素比最小元素大1 [1,1,1,1,1,2,1,1],此时返回1即可。因为maxV-minV=1,只能有1个bucket,下面的代码不适用。
  2. 因为map的原则都是往最近的大于等于该元素的bucket去map,最大的那个元素要特殊处理,应该map到bucket[bucketNum - 1]。
    代码如下:
struct bucketType {
    int count;
    int minNum;
    int maxNum;
    bucketType(int c = 0, int minV = INT_MAX, int maxV = 0) : count(c), minNum(minV), maxNum(maxV) {}
};

class Solution {
public:
    /**
     * @param nums: an array of integers
     * @return: the maximun difference
     */
    int maximumGap(vector<int> &nums) {
        int n = nums.size();
        if (n < 2) return 0;
        
        int minV = INT_MAX, maxV = INT_MIN;
        
        for (int i = 0; i < n; ++i) {
            minV = min(minV, nums[i]);
            maxV = max(maxV, nums[i]);
        }
        
        //special case [1,1,1,2,1,1], [1,1,1,1,1,1]
        if (maxV - minV <= 1) return maxV - minV; 
        
        int bucketNum = min(n, maxV - minV);   //important!!!
        int bucketLen = (maxV - minV) / bucketNum;
        vector<bucketType> buckets(bucketNum);
        
        // the buckets are [ ) range
        for (int i = 0; i < n; ++i) {
            int index = (nums[i] - minV) / bucketLen;
            if (index >= bucketNum) index = bucketNum - 1;
  
            buckets[index].count++;
            buckets[index].maxNum = max(buckets[index].maxNum, nums[i]);
            buckets[index].minNum = min(buckets[index].minNum, nums[i]);
        }

        int maxDist = 0;
        int lastElem = buckets[0].maxNum;
        for (int i = 1; i < bucketNum; ++i) {
            if (buckets[i].count == 0) continue;
            maxDist = max(maxDist, buckets[i].minNum - lastElem);
            lastElem = buckets[i].maxNum;
        }
        return maxDist;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值