计数排序和桶排序

本文介绍了计数排序和桶排序两种非比较型排序算法,包括它们的工作原理、适用范围和代码实现。计数排序通过统计数组中每个元素出现的次数,然后按顺序输出,适合于整数且范围不大的情况。桶排序则是将元素分配到不同的桶中,每个桶内部排序,最后合并所有桶,适用于分布均匀的数据。文中提供了Python和Java的代码示例来演示这两种排序算法的应用。
摘要由CSDN通过智能技术生成

刷到了一道leetcode算法题,虽然不难,但是却让我寸步难行,因为在此之前,我从未了解过计数排序和桶排序。

1. 题目分析

在这里插入图片描述
这道题看上去不难,但是若不了解计数排序和桶排序的概念,会绕很大的圈子,那我们现在来看一下什么是计数排序和桶排序。

2. 计数排序

目前我们所了解的最快的排序就是快速排序,但是有没有一些特定的情况,一些排序方式的速度超过快速排序呢?

1. 什么是计数排序?

计数排序是一种基于下标的排序,给出图解

  • 假定20个随机整数的值如下:
    9,3,5,4,9,1,2,7,8,1,3,6,5,3,4,0,10,9 ,7,9
  • 遍历这个数组
    比如第一个整数是9,那么数组下标为9的元素加1:
    在这里插入图片描述
    第二个整数是3,那么数组下标为3的元素加1:
    在这里插入图片描述
    继续遍历数列并修改数组…
    最终,数列遍历完毕时,数组的状态如下:
    在这里插入图片描述

数组每一个下标位置的值,代表了数列中对应整数出现的次数。

有了这个“统计结果”,排序就很简单了。直接遍历数组,输出数组元素的下标值,元素的值是几,就输出几次:

0,1,1,2,3,3,3,4,4,5,5,6,7,7,8,9,9,9,9,10

显然,这个输出的数列已经是有序的了。

2. 计数排序适用范围

当一个数组里的数全是整数,并且跨度不大,举几个例子。

  1. [2,3,6,9,8,7,4,5,6] 这个数组中值的范围是2~9,可以使用计数排序
  2. [2,100000,3,20000000] 这个数组中的范围太大了,不能使用计数排序
  3. [2,1.1,2.2] 存在小数,不能使用计数排序

3. 桶排序

1. 什么是桶排序?

顾名思义,就是一个一个的桶构成的排序,计数排序的弊端很大,桶排序是类似于计数排序的一种排序方式,不过桶排序的使用范围更广。
给出图解
每一个桶(bucket)代表一个区间范围,里面可以承载一个或多个元素。桶排序的第一步,就是创建这些桶,确定每一个桶的区间范围:
在这里插入图片描述
第二步,遍历原始数列,把元素对号入座放入各个桶中:
在这里插入图片描述
第三步,每个桶内部的元素分别排序(显然,只有第一个桶需要排序):
在这里插入图片描述
将桶里面的数据拿出来煤科院发现,已经是有序的了。

4. 代码实现

这道题我们用计数排序

1. Python代码

class Solution(object):
    def frequencySort(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        arr = [0 for _ in range(201)]
        res = [0 for _ in range(len(nums))]
        max1 = 0
        index = 0
        res_index = len(res) - 1
        for i in nums:
            arr[i + 100] += 1
        while True:
            max1 = 0
            index = 0
            for i in range(201):
                if arr[i] > max1:
                    max1 = arr[i]
                    index = i
            arr[index] = 0
            if max1 == 0:
                break
            for i in range(max1):
                res[res_index] = index - 100
                res_index -= 1
        return res

2. Java代码

class Solution {
    public int[] frequencySort(int[] nums) {
        int[] arr = new int[201];
        int[] res = new int[nums.length];
        int max = 0;
        int index = 0;
        for(int i:nums){
            arr[i + 100] += 1;
        }
        
        for(int j = res.length - 1;j >= 0;j--){
            max = 0;
            index = 0;
            for(int i = 0;i < arr.length;i++){
                if(arr[i] > max){
                    max = arr[i];
                    index = i;
                }
            }
            arr[index] = 0;
            if(max == 0){
                break;
            }
            for(int k = 0;k < max;k++){
                res[j] = index - 100;
                j--;
            }
            j++;
        }
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若能绽放光丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值