leetcode:164. 无序数组如果排序之后相邻数之间的最大差值

这篇博客介绍了如何运用桶排序算法解决LeetCode中的164.最大间距问题。通过假设数组区间并进行等分,创建桶来存储数值,然后找到空桶两侧的最大值和最小值来确定最大间距。这种方法有效地减少了比较次数,提高了效率。博客还讨论了如何确定数值应放入哪个桶,并提供了具体的代码实现。
摘要由CSDN通过智能技术生成

题目来源

题目描述

在这里插入图片描述

class Solution {
public:
    int maximumGap(vector<int>& nums) {

    }
};

题目解析

桶排序

借助桶排序的思想,假设答案法。

整个数组假设一共有9个数,其最小值是0,最大值是99。

那么我们将整个范围[0,99]10等分。

  • 为什么是10等分,因为一共有9个数
  • 如果有10个数,那么就将[0,99]11等分
  • 如果有11个数,那么就将[0,99]12等分
  • 如果有N个数,那么就把从[最小值,最大值]一共N+1等分

从而得到了10个桶:

  • 第0个桶只收集范围在0~10区间的数
  • 第1个桶只收集范围在11~21区间的数
  • 第2个桶只收集范围在22~32区间的数
  • 第3个桶只收集范围在33~43区间的数
  • 第4个桶只收集范围在44~54区间的数
  • 最后一个空只收集99

因此:

  • 最小值一定会进最左边的桶,最大值一定会近最右边的桶
    • (所以空桶一定不会出现在左右两侧)
    • 可能会存在多个空桶,空桶的边上可能是空桶
  • 一共有10个桶,但是只有9个数,所以中间一定会有一个空桶

如果拍完序之后: 相邻两数就可能来自同一个桶,也可能来自跨桶的

  • 空桶的左右两侧一定存在非空桶:
    • 左侧的非空桶的最大值,和左侧的非空桶的最小值一定相邻,而且它们之间的差值一定大于桶范围
    • 来自同一个桶的数一定不是我们要找的。因为同一个桶的相邻数减完之后差值不会大于桶区间;
    • 这就排除了一大票可能的数,因此每个桶我们只需要维护其最大值和最小值即可,完全不需要考虑桶内的数据是怎么分布的
  • 最大值一定来自空桶两侧吗?不一定

问题:怎么决定nums[i]应该进哪个桶?

int bucket(int num, int len, int min, int max){
    return (int) ((num - min) * len / (max - min));
}

怎么分,不重要,关键是桶排序

举个例子

在这里插入图片描述

实现

class Solution {
    int bucket(long num, long len, long min, long max) {
        return (int) ((num - min) * len / (max - min));
    }
public:
    int maximumGap(vector<int>& nums) {
        if(nums.size() < 2){
            return 0;
        }

        int len = nums.size();
        int min = INT32_MAX, max = INT32_MIN;
        for (int i = 0; i < len; ++i) {
            min = std::min(min, nums[i]);
            max = std::max(max, nums[i]);
        }
        if(max == min){
            return 0;
        }
        int bucketSize = len + 1;
        std::vector<bool> hasNum(len + 1, false);
        std::vector<int> maxs(len + 1, INT32_MIN);
        std::vector<int> mins(len + 1, INT32_MAX);
        int bid = 0;
        for (int i = 0; i < len; i++) {
            bid = bucket(nums[i], bucketSize - 1 , min, max);
            mins[bid] = hasNum[bid] ? std::min(mins[bid], nums[i]) : nums[i];
            maxs[bid] = hasNum[bid] ? std::max(maxs[bid], nums[i]) : nums[i];
            hasNum[bid] = true;
        }

        int ans = INT32_MIN;
        int lasMax = maxs[0];  // 左右两侧一定不是空桶
        for (int i = 1; i <= len; ++i) {
            if(hasNum[i]){
                ans = std::max(ans, mins[i] - lasMax); //相邻的数
                lasMax = maxs[i];
            }
        }
        return ans;
    }
};

桶排序

在这里插入图片描述


基数排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值