计数排序
来源:互联网 发布:淘宝抢购秒杀器哪个好 编辑:程序博客网 时间:2024/05/17 04:00
起源:
今天用计数排序解决了几道问题,感觉这个算法很有用,于是仔细研究了下,并且在《算法导论》一书中读到了相关的内容。
计数排序的优势
计数排序的时间复杂度为O(n+ k)..其中要设定一个辅助count数组。统计原数组中,每个元素出现的次数。
直观的感觉是记录<=x元素的个数,那么把x元素放到后面就可以了,那么就将所有的元素都排好序了,但是这种思想还需要一个临时数组存储排好序的数组。
通俗地理解,例如有10个年龄不同的人,统计出有8个人的年龄比A小,那A的年龄就排在第9位,用这个方法可以得到其他每个人的位置,也就排好了序。当然,年龄有重复时需要特殊处理(保证稳定性),这就是为什么最后要反向填充目标数组,以及将每个数字的统计减去1的原因。
算法的步骤如下:
1找出待排序的数组中最大和最小的元素
2统计数组中每个值为i的元素出现的次数,存入数组 C 的第 i 项
//得到小于等于x元素的个数
3对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
//保持稳定性
4 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1.
实践
颜色分类
给定一个包含红,白,蓝且长度为 n 的数组,将数组元素进行分类使相同颜色的元素相邻,并按照红、白、蓝的顺序进行排序。
我们可以使用整数 0,1 和 2 分别代表红,白,蓝。
给你数组 [1, 0, 1, 2], 需要将该数组排序为 [0, 1, 1, 2]。
class Solution { /** * @param nums: A list of integer which is 0, 1 or 2 * @return: nothing */ public void sortColors(int[] nums) { // write your code here if (nums == null || nums.length == 0){ return; } int[] count = new int[3]; int[] tmp = new int[nums.length]; for (int i = 0; i < nums.length; i++){ count[nums[i]]++; } for (int i = 1; i < count.length; i++){ count[i] += count[i - 1]; } for (int j = nums.length - 1; j >= 0; j--){ tmp[count[nums[j]] - 1] = nums[j]; count[nums[j]]--; } for (int i = 0; i < nums.length; i++){ nums[i] = tmp[i]; } }}
思考一步:
这种解法可以优化的地方在于不一定需要临时数组tmp,因为count数组得下标对应的为nums[i]中的元素,而且数组下标肯定是有序的,所以直接填充就好。
class Solution { /** * @param nums: A list of integer which is 0, 1 or 2 * @return: nothing */ public void sortColors(int[] nums) { // write your code here if (nums == null || nums.length == 0){ return; } int[] count = new int[3]; int[] tmp = new int[nums.length]; for (int i = 0; i < nums.length; i++){ count[nums[i]]++; } int index = 0; for (int j = 0; j < count.length; j++){ while (count[j]-- > 0){ nums[index++] = j; } } }}
注意这里我定义了全局索引index,用来扫描原始数组的空间。
大同小异
排颜色follow up
给定一个有n个对象(包括k种不同的颜色,并按照1到k进行编号)的数组,将对象进行分类使相同颜色的对象相邻,并按照1,2,…k的顺序进行排序。
给出colors=[3, 2, 2, 1, 4],k=4, 你的代码应该在操作使得数组变成[1, 2, 2, 3, 4]
class Solution { /** * @param colors: A list of integer * @param k: An integer * @return: nothing */ public void sortColors2(int[] colors, int k) { // write your code here if (colors == null || colors.length == 0 || k <= 0){ return; } int[] count = new int[k + 1]; for (int i = 0; i < colors.length; i++){ count[colors[i]]++; } int index = 0; for (int i = 0; i < count.length; i++){ while (count[i]-- > 0){ colors[index++] = i; } } }}
这个地方没有0,所以要自己补统计0的个数
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- 计数排序
- maven项目的创建
- 基于INT类型的多分类传输
- 学习jsp时遇见的几个问题
- AndroidStudio如何提示函数用法
- Android 4.4(KitKat)中的设计模式-Graphics子系统
- 计数排序
- ACM--三个水杯
- AndroidStudio代码提示
- 02 Bean的相关概念
- React native 的轮播图组件react-native-image-carousel的使用
- Qt数据库sqlite总结
- 实现波纹效果
- Hibernate与Jpa的关系, Spring JpaTransactionManager事务管理
- Android图集的上下左右拖动及动画效果研究