[leetcode] 164. Maximum Gap

题目链接:https://leetcode.com/problems/maximum-gap/
题意:给定一个无序数组,求有序情况下相邻元素差最大为多少?
要求:时间复杂度和空间复杂度均为O(n)

法一:我们很容易能够想到基数排序,它的时间复杂度和空间复杂度都是O(n),排好序之后扫一遍就行了。这样当然是没有问题的。代码如下:

class Solution {
public:

    void radixSort(vector<int>& nums)
    {
        int b = sizeof(int);
        int n = nums.size();
        vector<int> tmp(n,0);
        for(int t=0; t<b; ++t){
            vector<int> c(256,0);
            for(int i=0; i<n; ++i){
                int p = 255&(nums[i]>>(t*8));
                ++ c[p];
            }
            c[255] = n - c[255];
            for(int i=254; i>=0; --i){
                c[i] = c[i+1] - c[i];
            }
            for(int i=0; i<n; ++i){
                int p = 255&(nums[i]>>(t*8));
                tmp[c[p]++] = nums[i];
            }
            nums = tmp;
        }
        int k = n;
        for(int i=n-1; i>=0; --i){
            if(nums[i] > 0){
                k = i+1;
                break;
            }
        }
        int t = 0;
        for(int i=k; i<n; ++i){
            nums[t++] = tmp[i];
        }
        for(int i=0; i<k; ++i){
            nums[t++] = tmp[i];
        }
    }

    int maximumGap(vector<int>& nums) {
        int n = nums.size();
        if(n < 2)  return 0;
        int ret = 0;
        radixSort(nums);
        for(int i=1; i<n; ++i){
            ret = max(ret, nums[i]-nums[i-1]);
        }
        return ret;
    }
};

法二:有没有一种不需要排序的方法呢?我们可以借鉴前面的基数排序的思想,考虑桶排序:假设数组中最大元素是maxx,最小元素是minx,则平均间隔为avg = floor((maxx-minx)/n);那么max gap一定大于等于avg。利用avg可以将数组分成(maxx-minx)/avg+1个桶。那么max gap应该在相邻两个不为空的桶max(min(p2) - max(p1) )中。整体的话就是分为两步:分桶;统计。代码如下:

class Solution {
public:
    int maximumGap(vector<int>& nums){
        int n = nums.size();
        if(n < 2)  return 0;
        int ret = 0;
        int minx = nums[0], maxx = nums[0];
        for(int i=1; i<n; ++i){
            if(nums[i] > maxx)  maxx = nums[i];
            if(nums[i] < minx)  minx = nums[i];
        }
        if(maxx == minx)   return 0;
        int avg = (maxx-minx)/n;  //  max gap必然 >= avg
        if(avg == 0)  ++ avg;
        ret = avg;
        int m = (maxx - minx)/avg + 1;
        vector<int> h1(m,INT_MIN), h0(m,INT_MAX);  // 保存每个桶中的最大值和最小值
        for(int i=0; i<n; ++i){
            int p = (nums[i] - minx)/avg;
            if(nums[i] > h1[p]){
                h1[p] = nums[i];
            }
            if(nums[i] < h0[p]){
                h0[p] = nums[i];
            }
        }
        int pre = 0;
        for(int i=1; i<m; ++i){
            if(h0[i] < INT_MAX){
                if(h0[i] - h1[pre] > ret){
                    ret = h0[i] - h1[pre];
                }
                pre = i;
            }
        }
        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值