桶排序中对计算第几只桶的疑问

桶排序中对计算第几只桶的疑问

http://img1.sycdn.imooc.com//climg/6072ebc7098acbd920241200.jpg

老师,如上图所示,

课程内计算第几只桶是 (e-minv) / c, 我的问题就在这里,比如当前c=3,  e=100, maxv=10000, minv=0, arr=[0, 1, 2, 999, 1001, 1002, 10000], B= Math.ceil(7/3) => 3只桶

​,如果按照 (e-minv) / c计算, 那么此时  (10000-0) / 3=>超出桶的数量了(10000这个数没地方放了)

而如果按照每只桶的数据范围来看, range = (10000-0) / 3 => 3333.333=>3334

那么此时 (10000-0)/3334=》3,说明此时10000放在第3只桶里

========

以上就是我的理解,我是按照红框部分改版来做的 :)


正在回答

登陆购买课程后可参与讨论,去登陆

1回答

啊哦!这里确实我的代码错了!感谢提醒!我有时间修改一下这一小节的视频。


抱歉!


==========


修改后的完整代码如下:


public static void sort2(Integer[] arr, int c){
        
    if(c <= 0)
        throw new IllegalArgumentException("c must be > 0");
    
    // 首先,需要计算 arr 中的数据范围    
    int maxv = Integer.MIN_VALUE, minv = Integer.MAX_VALUE;
    for(int e: arr){
        maxv = Math.max(maxv, e);
        minv = Math.min(minv, e);
    }
    int range = maxv - minv + 1; // arr 中的数据范围
    
    // 根据数据范围 range 和每个桶中最多可容纳的元素,计算桶的个数 B 
    int B = range / c + (range % c > 0 ? 1 : 0); // 根据数据范围决定桶的个数
        
    // 开设桶
    LinkedList<Integer>[] buckets = new LinkedList[B];
    for(int i = 0; i < B; i ++)
        buckets[i] = new LinkedList<>();
    
    // 把数据放入桶中
    for(int e: arr)
        buckets[(e - minv) / c].add(e);
        
    // 对每一个桶排序
    for(int i = 0; i < B; i ++)
        Collections.sort(buckets[i]);
        
    // 重新整理所有数据
    int index = 0;
    for(int i = 0; i < B; i ++)
        for(int e: buckets[i])
            arr[index ++] = e;
    }
}


对于这个代码,我使用 Leetcode 164 进行了测试:https://leetcode-cn.com/problems/maximum-gap/


测试代码如下(直接复用上面的算法类。因为 164 问题给的是 int[],也可以针对 int[] 再实现一遍桶排序。)


class Solution {
    public int maximumGap(int[] nums) {
        if(nums.length < 2) return 0;
        Integer[] data = Arrays.stream(nums).boxed().toArray( Integer[]::new );
        BucketSort.sort2(data, 100000);
        for(int e: data) System.out.println(e);
        int res = data[1] - data[0];
        for(int i = 2; i < data.length; i ++)
            res = Math.max(res, data[i] - data[i - 1]);
        return res;
    }
}


是可以获得通过的。


这个代码我也已经更新到了课程的官方代码仓中,可以参考这里:https://git.imooc.com/class-105/Play-Algorithms-and-Data-Structures/src/master/30-MSD-Radix-Sort-and-Bucket-Sort/07-Bucket-Sort2/src/BucketSort.java


继续加油!:)

  • Mr__Xin #1
    老师,如果写为buckets[(e-minV)/range].add(e),buckets内部索引值会始终为0,所有的元素都会集中在第一个桶内。所以,我个人感觉,原先这个版本是正确的。
    2022-02-04 00:59:51
  • liuyubobobo 回复 Mr__Xin #2

    咦?好奇怪,我查提交给力扣测试的代码是正确的,这个答案之前的代码确实有误。你说的这句话应该是 buckets[(e - minv) / c].add(e);,否则如你所说,所有的元素都会集中在第一个桶中。(现在我已经将这个答案下的代码修改了。抱歉。)


    课程之前的代码错误的核心原因是:计算 B,应该由数据范围决定(即这个答案中的 range),而不是由元素个数决定。

    2022-02-05 05:26:48
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
算法与数据结构
  • 参与学习       2594    人
  • 解答问题       1091    个

慕课网算法名师Liuyubobobo,5年集大成之作 从0到工作5年,算法与数据结构系统解决方案

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师