桶排序算法:topK元素golang实现

本文介绍桶排序原理及其在解决Top K元素问题中的应用。通过将数据均匀分布到桶中,实现高效查找高频元素。文章包含具体实现代码及测试案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先介绍一下桶思想:

     在现实世界中,大部分的数据分布是均匀的,或者在设计的时候让它可以均匀分布,或者说可以转换为均匀的分布。

数据均匀分布了,桶排序的效率就能发挥出来。(分库分表)

误区:    1.如果数据分布不均匀,大量的数据集中在少数桶里,桶排序就没效果了。

               2、桶排序要时间就省不了空间,要空间就省不了时间。结论是桶排序意义不大。

桶排序或所谓的箱排序

桶排序(Bucket sort)的原理:

假如输入的数据服从均匀分布,将数据分到有限数量的桶里,然后对每个桶分别进行排序,最后把 桶的数据全部合并。

桶排序的时间复杂度,取决于对各桶之间数据进行排序的时间复杂度,因为其他部分的时间复杂度都为O(n)。显然,桶划分的越小,各个桶之间的数据越少排序所用的时间也会越少。但相应的空间消耗就会增大

例子力扣算法题目:topK元素(前K个高频元素)要求时间复杂度优于O(nlogn)。

解题思路:

       1、使用字典统计数组中每个元素出现的频率key=元素,value=元素出现的频率

       2、使用一维数组构造桶桶的数目小于等于数组中元素的个数,将频率作为一维数组下标,对于出现不同频率的元素集合,存入对应的一维数组下标,桶的长度取数组长度+1;

       3、倒序遍历一维数组,获取出现频率送达到小的排列, result中的元素超过k退出遍历即可

func topKElem(nums []int, k int) (result []int) {
	 /*字典统计数组中每个元素出现的频率*/
    frequence := map[int]int{}
	for _, num := range nums {
		if _, ok := frequence[num]; ok {
			frequence[num] += 1
		} else {
			frequence[num] = 1
		}
	}
   /*将频率作为一维数组下标,对于出现不同频率的元素集合,存入对应的一维数组下标*/
	freqArr := make([]int, len(nums)+1)
	for elem, freq := range frequence {
		freqArr[freq] = elem
	}
  /* 倒序遍历一维数组,获取出现频率送达到小的排列, result中的元素超过k退出遍历即可*/
	for i := len(freqArr) - 1; i >= 0; i-- {
		if freqArr[i] != 0 && len(result) < k {
			result = append(result, freqArr[i])
		}
	}
	return result
}
func topKElem(nums []int, k int) (topKIds []int) {
	 /*字典统计数组中每个元素出现的频率*/
    frequence := map[int]int{}
	for _, num := range nums {
		if _, ok := frequence[num]; ok {
			frequence[num] += 1
		} else {
			frequence[num] = 1
		}
	}    
    
	res := make([][]int, len(nums)+1)
	maxFreq := 0
	for id, freq := range frequence {
		if freq > maxFreq {
			maxFreq = freq
		}
		if res[freq] != nil {
			res[freq] = append(res[freq], id)
		} else {
			res[freq] = []int{id}
		}
	}

	for i := maxFreq; len(topKIds) < k; i-- {
		for j := 0; j < len(res[i]); j++ {
			topKIds = append(topKIds, res[i][j])
			if len(topKIds) >= k {
				break
			}
		}
	}
return 
}

 

测试结果:

func main(){    
    nums := []int{1, 1, 6}
	fmt.Println(topKElem(nums, 2))


}

>>[1 6]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值