[LeetCode] Maximum Gap

Maximum Gap

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.

Credits:
Special thanks to @porker2008 for adding this problem and creating all test cases.

解题思路:

1、最传统的思路,先给数组排序,然后遍历数组,找到最大的差值。这种方法时间复杂度为O(nlogn),空间复杂度为O(1),不满足题目要求。

2、我想到了set会自动给元素排序,逐一插入set数组,然后遍历set中的元素,求出最大差值。后来查资料发现,set元素的插入、查找操作的时间复杂度为O(logn),总时间复杂度为O(nlogn),不符合题目要求。

3、因为给出的是正整数,因此可以考虑基数排序。基数排序的时间复杂度为O(k*n),k是一个小整数,空间复杂度为O(n),因此满足要求。代码如下:

class Solution {
public:
	int maximumGap(vector<int> &num) {
		int count = num.size();
		if (count < 2){
			return 0;
		}
		int max = num[0];
		int min = num[0];
		for (int i = 1; i<count; i++){
			max = max > num[i] ? max : num[i];
			min = min > num[i] ? num[i] : min;
		}
		if (max == min){
			return 0;
		}
		int maxLen = getNumberLength(max);
		//基数排序
		int base = 1;   //n位
		vector<int> bucket[10];
		for (int i = 0; i< maxLen; i++){
			for (int j = 0; j < count; j++){
				bucket[getSpecialPostionNumber(num[j], base)].push_back(num[j]);
			}
			num.clear();
			for (int j = 0; j < 10; j++){
				for (int k = 0; k < bucket[j].size(); k++){
					num.push_back(bucket[j][k]);
				}
				bucket[j].clear();
			}
			base *= 10;
		}

		int maxGap = 0;

		for (int i = 1; i < count; i++){
			maxGap = maxGap > num[i] - num[i - 1] ? maxGap : num[i] - num[i - 1];
		}

		return maxGap;
	}
private:
	//获得特定位上的数字,i表示1位,10位等
	int getSpecialPostionNumber(int num, int i){
		return (num / i) % 10;
	}
	//获得数字的长度
	int getNumberLength(int num){
		int len = 0;
		while (num != 0){
			len++;
			num /= 10;
		}
		return len;
	}
};

4、官方给出的办法类似于桶排序。它也符合负数的情况(若有负数,需要考虑溢出的情况)。大体思想为;

假设有N个元素A到B。
那么最大差值不会小于ceiling[(B - A) / (N - 1)](均匀差时最大差值最小)
令bucket(桶)的大小len = ceiling[(B - A) / (N - 1)],则最多会有(B - A) / len + 1个桶
对于数组中的任意整数K,很容易通过算式loc = (K - A) / len找出其桶的位置,然后维护每一个桶的最大值和最小值
由于同一个桶内的元素之间的差值至多为len - 1,因此最终答案不会从同一个桶中选择。
对于每一个非空的桶p,找出下一个非空的桶q,则q.min - p.max可能就是备选答案。返回所有这些可能值中的最大值。

代码如下:

class Solution {
public:
    int maximumGap(vector<int> &num) {
       if (num.size() < 2) return 0;
        //遍历一遍,找出最大最小值
        int maxNum = num[0];
        int minNum = num[0];
        for (int i : num) {
            maxNum=max(maxNum,i);
            minNum=min(minNum,i);
        }
        // 每个桶的长度len,向上取整所以加+
        int len = (maxNum - minNum) / num.size() + 1;
        
        //桶的个数:(maxNum - minNum) / len + 1,每个桶里面存储属于该桶的最大值和最小值即可,注意这里的最大最小值是局部的
        vector<vector<int>> buckets((maxNum - minNum) / len + 1);
        for (int x : num) {
            int i = (x - minNum) / len;
            if (buckets[i].empty()) {
                buckets[i].reserve(2);
                buckets[i].push_back(x);
                buckets[i].push_back(x);
            } else {
                if (x < buckets[i][0]) buckets[i][0] = x;
                if (x > buckets[i][1]) buckets[i][1] = x;
            }
        }
        //gap的计算,For each non-empty buckets p, find the next non-empty buckets q, return min( q.min - p.max )
        int gap = 0;
        int prev = 0;
        for (int i = 1; i < buckets.size(); i++) {
            if (buckets[i].empty()) continue;
            gap = max(gap, buckets[i][0] - buckets[prev][1]);
            prev = i;
        }
        return gap;
    }
};


0 条评论

    发表评论

    电子邮件地址不会被公开。 必填项已用 * 标注