github仓库
https://github.com/jackzcai/golang-interview
概述
计数排序是一种线性时间的整数排序算法。如果数组的长度为n,整数范围为k,对于k远小于n的场景,那么计数排序的时间复杂度优于其它基于比较的排序算法。
基本思想
先统计数组中每个整数出现的次数,然后按照从小到大的顺序将每个整数按照它出现的次数填到数组中。
使用count数组统计数字出现的次数,count数组的长度就设置为nums数组中最大值减最小值+1。
总共经过三次循环
第一次循环得出最大最小值。
第二次循环通过最大最小值构建count数组,并往count数组对应位置填入出现次数。
第三次循环count数组,并将对应位置的值从头填写入nums数组中,填写次数为count数组的值。
源码
package main
import (
"fmt"
"math"
)
func main() {
nums := []int{23, 56, 34, 45, 23, 46, 34, 46, 34, 456, 65, 67, 45, 56, 2, 5, 32, 6, 8, 34, 7, 3, 8, 9, 23}
countsort(nums)
fmt.Printf("%v\n", nums)
}
func countsort(nums []int) {
minn := math.MaxInt64
maxn := math.MinInt64
for _, n := range nums {
minn = min(n, minn)
maxn = max(n, maxn)
}
count := make([]int, maxn-minn+1)
for _, n := range nums {
count[n-minn]++
}
numsi := 0
for i, _ := range count {
for count[i] > 0 {
nums[numsi] = i + minn
numsi++
count[i]--
}
}
}
func min(i, j int) int {
if i < j {
return i
} else {
return j
}
}
func max(i, j int) int {
if i > j {
return i
} else {
return j
}
}
复杂度
如果数组的长度为n,整数的范围为k,那么计数排序的时间复杂度就是O(n+k)。由于需要创建辅助数组count,空间复杂度为Ok。当k较小时,计数排序的时空间复杂度都是非常高效的。当k很大时,计数排序就不如其它排序算法高效了。