leetcode-164- 最大间距(快速排序+计数排序+基数排序+桶排序)

题目要求

给定一个无序的数组,找出数组在排序之后,相邻元素之间最大的差值。

如果数组元素个数小于 2,则返回 0。

示例 1:

输入: [3,6,9,1]
输出: 3
解释: 排序后的数组是 [1,3,6,9], 其中相邻元素 (3,6) 和 (6,9) 之间都存在最大差值 3。

示例 2:

输入: [10]
输出: 0
解释: 数组元素个数小于 2,因此返回 0。
说明:

你可以假设数组中所有元素都是非负整数,且数值在 32 位有符号整数范围内。
请尝试在线性时间复杂度和空间复杂度的条件下解决此问题。

完整代码如下:
#include<vector>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>

using namespace std;

//方法一
//使用STL中的sort排序做法,时间复杂度为O(nlogn),能够通过测试用例
//int maximumGap(vector<int>& nums) {
//    sort(nums.begin(), nums.end());
//    int preNum = -1;
//    int nowNum = -1;
//    int maxDif = 0;
//    for (auto iter = nums.begin(); iter != nums.end(); ++iter)
//    {
//        nowNum = *iter;
//        if (preNum >= 0)
//            maxDif = max(maxDif, nowNum - preNum);
//        preNum = nowNum;
//    }
//    return maxDif;
//}

//方法二
//未优化的计数排序,new申请内存时出错bad_alloc分配失败,原因是测试用例中最大值过大,超出堆所能申请的大小范围。
//int maximumGap(vector<int>& nums) {
//    if (nums.size() < 2)
//        return 0;
//    int maxnum = 0;
//    int minnum = 0x7fffffff;
//    for (auto i = nums.begin(); i != nums.end(); ++i)
//    {//找到最大值
//        if (*i > maxnum)
//            maxnum = *i;
//        if (*i < minnum)
//            minnum = *i;
//    }
//    if (minnum == maxnum)//如果最大值等于最小值
//        return 0;
//    //创建一个极大的数组
//    int* maxnumArray = new int[maxnum - minnum + 1];
//    memset(maxnumArray, 0xff, sizeof(int) * (maxnum - minnum + 1));
//    for (auto i = nums.begin(); i != nums.end(); ++i)
//        ++maxnumArray[*i-minnum];
//    int maxDif = 0;//最大插值
//    int preNum = -1;//上一个数的值
//    int nowNum = -1;//这一个数的值
//    for (int i = 0; i <= maxnum; i++)
//    {
//        if (maxnumArray[i] >= 0)
//        {//有等于i的数
//            nowNum = i;
//            if (nowNum >= 0 && preNum >= 0)
//            {
//                maxDif = max(maxDif, nowNum - preNum);
//            }
//            preNum = i;
//        }
//
//    }
//    delete[] maxnumArray;
//    return maxDif;
//}

//方法三,基数排序,能通过所有测试用例
//int maximumGap(vector<int>& nums)
//{
//    if (nums.size() <= 1)
//        return 0;
//    int maxNum = 0;
//    for (int i = 0; i < nums.size(); ++i)
//    {
//        if (nums[i] > maxNum)
//            maxNum = nums[i];
//    }
//    vector<vector<int>> baseArrays(10);//baseArrays中分别保存除以基数后取模为i的值
//    //例如对于{134,465,636},首先对于个位数,134放入baseArrays[4],对于10位数,465放入baseArrays[6]
//    int baseNum = 10;//底数为10
//    int exp = 1;//10的n次方
//    int tempNum;
//    while (maxNum / exp)
//    {
//        for (int i = 0; i < nums.size(); ++i)
//        {//将nums所有元素存放在baseArrays中
//            tempNum = nums[i];
//            baseArrays[(tempNum / exp) % 10].push_back(tempNum);
//        }
//        nums.clear();//清空nums元素
//        //按顺加入nums中
//        for (auto baseArray : baseArrays)
//            for (auto arrayNum : baseArray)
//                nums.push_back(arrayNum);
//        for (int i = 0; i < 10; ++i)
//        {//清空baseArrays
//            baseArrays[i].clear();
//        }
//        exp *= baseNum;
//    }
//    int maxDif = 0;
//    for (int i = 0; i < nums.size() - 1; ++i)
//    {
//        maxDif = max(maxDif, nums[i + 1] - nums[i]);
//    }
//    return maxDif;
//}

//桶结构体
struct Bucket
{
    bool USED = false;
    int MAXNUM = 0;         //设为最小无符号整数
    int MINNUM = 0x7fffffff;//设为最大整数
};

//桶排序
int maximumGap(vector<int>& nums)
{
    if (nums.size() <= 1)
        return 0;
    int maxNum = 0;
    int minNum = 0x0fffffff;
    for (int i = 0; i < nums.size(); i++)
    {
        maxNum = max(maxNum, nums[i]);
        minNum = min(minNum, nums[i]);
    }
    //桶的大小,桶的大小需要小于等于平均间距,同时
    //对区间采用左闭右开,这样桶内元素之间的大小一定不是最大间距
    int bucket_size = max(1,(maxNum - minNum) / (int)(nums.size() - 1));
    //桶的个数,桶的个数乘以桶的大小应该大于max - min
    int bucket_num = (maxNum - minNum) / bucket_size + 1;
    int bucket_index;//桶序号
    vector<Bucket> buckets(bucket_num);//初始化桶
    for (int i = 0; i < nums.size(); ++i)
    {//放入桶
        bucket_index = (nums[i] - minNum) / bucket_size;
        buckets[bucket_index].USED = true;
        buckets[bucket_index].MAXNUM = max(nums[i], buckets[bucket_index].MAXNUM);
        buckets[bucket_index].MINNUM = min(nums[i], buckets[bucket_index].MINNUM);
    }
    int preMax = minNum;//前一个桶的最大值,初始值设为nums最小值
    int maxDiff = 0;//最大间距
    Bucket temp;
    for (int i = 0; i < bucket_num; i++)
    {
        temp = buckets[i];
        if (temp.USED)
        {//如果该桶使用过
            maxDiff = max(maxDiff, temp.MINNUM - preMax);//更新间距
            preMax = temp.MAXNUM;
        }
    }
    return maxDiff;
}

int main()
{
    vector<int> i = {601408776,63967816,431363697,242509930,15970592,60284088,228037800,147629558,220782926,55455864,456541040,106650540,17290078,52153098,103139530,294196042,16568100,426864152,61916064,657788565,166159446,1741650,101791800,28206276,6223796,524849590,125389882,84399672,153834912,164568204,1866165,283209696,560993994,16266096,219635658,9188983,485969304,782013650,120332636,44659356,444517408,36369045,47370708,18542592,98802990,137690000,124889895,56062800,265421676,309417680,4634176,801661539,510541206,258227892,398938089,47255754,152260962,409663140,102847688,45756553,377936600,269498,375738702,263761134,53797945,329493948,224442208,508336845,189507850,40944620,127879560,119629476,186894520,62409156,693721503,4289916,523899936,28955240,266488028,20356650,40769391,483694272,97988044,84102,67246047,310688630,41288643,58965588,42881432,152159462,94786355,174917835,119224652,525034376,261516,274800528,62643819,23613832,8397240,797832131,855155367,337066320,26341480,61932200,20661075,515542796,390337500,522552030,43538516,150800550,116747540,152989123,488640056,700610304,233604,344277340,21439176,9397864,16365822,73027584,453041413,197374275,157735188,15273822,187081152,379611084,865005504,223099767,80478651,377729400,186738219,34738263,16634072,112791343,99631856,119364960,477106486,583953920,624509809,188442472,294181256,213023715,146645884,149530380,497592753,132170327,72770643,126683010,405141255,590214306,26670714,95582385,162080790,231120099,8946432,204967980,592849110,54120698,375915096,602145859,5346440,226337825,425156369,653591624,578483360,572410800,32290700,381384563,149939976,183225375,155695620,38307636,457513760,97085778,75200576,8068176,221650296,556889418,252495726,895020231,19932465,156334887,191383314,348432526,368701264,14315598,148936587,279419435,237325542,252587218,322929504,26331343,355297676,600420786,652017765,51673622,159015675};
    cout << maximumGap(i) << endl;
    vector<int>j = { 1,1,1 };
    cout << maximumGap(j);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值