从leetcode上发现的问题
计数排序
- 先把数组中的每个数进行计数
- 正向计算累加数组(其实是为了计算每个数(包括自己)前面有多少个数)
- 反向(为了保持稳定排序,这在后面的基数排序中非常重要)把每个数放到它对应的位置。
1 | for (int i = 0; i < n; ++i) |
基数排序
其实就是对每一位进行计数排序, 不停地迭代排序得到最终的有序数组,例题:164. 最大间距
- 选定一个基数
base
作为基数排序的超参数(二进制基数排序就是2,十进制就是10,这个影响不大) - 把每一个数在
base
进制下的第k
位数字作为key
进行计数排序
这里实现的是简单的低位到高位的基数排序,代码简单好写,但这里的计数排序最后一定要逆序遍历放置。否则低位到高位的基数排序会出现以下情况
021、041、061、171,加粗表示当前对2位进行计数排序
那么此时cnt[0] = 3, cnt[1] = 1, 累加之后变为cnt[0] = 3, cnt[1] = 4
如果正序,
那么b[—cnt[0]] = 012, 即b[2] = 021,
接着b[—cnt[0]] = 041, 即b[1] = 041,
接着b[—cnt[0]] = 061, 即b[0] = 061,
最后b[—cnt[1]] = 171, 即b[3] = 171
可以发现021,041,061顺序反了,这是因为正序不能保证计数排序是稳定排序,而基数排序中对当前第k位的计数排序需要稳定排序,即当key值相同时,要按照在第k-1位排序中的顺序进行排序
1 | int n = nums.size(); |