左神算法-基础03
2021/10/29 20:09:55
本文主要是介绍左神算法-基础03,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
左神算法-基础03
比较器的使用
1)比较器的实质就是重载比较运算符
2)比较器可以很好的应用在特殊标准的排序上
3)比较器可以很好的应用在根据特殊标准排序的结构上
public static class MyComp implements Comparator<Integer> { //实现Comparator 接口,重写compare()方法,实现自己的比较逻辑 //返回负数时,第一个参数排前面 //返回正数时,第二个参数排前面 //返回0 时,谁在前面无所谓 @Override public int compare(Integer o1, Integer o2) { return o2 - o1; } }
桶排序思想下的排序
1)计数排序
2)基数排序
分析:
1) 桶排序思想下的排序都是不基于比较的排序
2) 时间复杂度为O(N),额外空间负载度O(M)
3) 应用范围有限,需要样本的数据状况满足桶的划分
// only for 0~200 value 计数排序 public static void countSort(int[] arr) { if (arr == null || arr.length < 2) { return; } int max = Integer.MIN_VALUE; for (int i = 0; i < arr.length; i++) { //找到最大值 max = Math.max(max, arr[i]); } int[] bucket = new int[max + 1]; //申请桶子 for (int i = 0; i < arr.length; i++) { bucket[arr[i]]++; //在桶子里放数 } int i = 0; for (int j = 0; j < bucket.length; j++) { while (bucket[j]-- > 0) { //按顺序将每个桶子里的数字,还原到数组中 arr[i++] = j; } } }
// only for no-negative value 基数排序 public static void radixSort(int[] arr) { if (arr == null || arr.length < 2) { return; } radixSort(arr, 0, arr.length - 1, maxbits(arr)); } public static int maxbits(int[] arr) { int max = Integer.MIN_VALUE; for (int i = 0; i < arr.length; i++) { //找到最大值 max = Math.max(max, arr[i]); } int res = 0; while (max != 0) { //算出最大值有多少个十进制位 res++; max /= 10; } return res; //返回最大的进制位数 } public static void radixSort(int[] arr, int begin, int end, int digit) { final int radix = 10; //默认是十进制,十个基数:0,1,2,3,4,5,6,7,8,9 int i = 0, j = 0; int[] bucket = new int[end - begin + 1]; for (int d = 1; d <= digit; d++) { int[] count = new int[radix]; //计数数组 for (i = begin; i <= end; i++) { j = getDigit(arr[i], d); //得到d 位上的基数 count[j]++; //该基数位置加一 } for (i = 1; i < radix; i++) { count[i] = count[i] + count[i - 1]; //计算出每个位置的前缀和 } for (i = end; i >= begin; i--) { //从后往前遍历,可以将上一轮基数排序的顺序保存下来 j = getDigit(arr[i], d); bucket[count[j] - 1] = arr[i]; //<=j 的数有count[j]个,将arr[i]放到count[j]-1的位置上去 count[j]--; //<=j 的数减一 } for (i = begin, j = 0; i <= end; i++, j++) { arr[i] = bucket[j]; //从bucket 放回原数组 } } } public static int getDigit(int x, int d) { //计算d 位上的基数,也就是取余操作 return ((x / ((int) Math.pow(10, d - 1))) % 10); }
排序算法的稳定性及其汇总
同样值的个体之间,如果不因为排序而改变相对次序,就是这个排序是有稳定性的;否则就没有。
不具备稳定性的排序:
选择排序、快速排序、堆排序
具备稳定性的排序:
冒泡排序、插入排序、归并排序、一切桶排序思想下的排序
目前没有找到时间复杂度O(N*logN),额外空间复杂度O(1),又稳定的排序。
时间复杂度 | 空间复杂度 | 稳定性 | |
---|---|---|---|
选择排序 | O(N^2) | O(1) | 否 |
冒泡排序 | O(N^2) | O(1) | 是 |
插入排序 | O(N^2) | O(1) | 是 |
归并排序 | O(N*logN) | O(N) | 是 |
快速排序 | O(N*logN) | O(logN) | 否 |
堆排序 | O(N*logN) | O(1) | 否 |
排序算法常见的坑
1,归并排序的额外空间复杂度可以变成O(1),但是非常难,不需要掌握,有兴趣可以搜“归并排序 内部缓存法”
2,“原地归并排序”的帖子都是垃圾,会让归并排序的时间复杂度变成O(N^2)
3,快速排序可以做到稳定性问题,但是非常难,不需要掌握, 可以搜 “01 stable sort”
4,所有的改进都不重要,因为目前没有找到时间复杂度O(N*logN),额外空间复杂度O(1),又稳定的排序。
5,有一道题目,是奇数放在数组左边,偶数放在数组右边,还要求原始的相对次序不变,碰到这个问题,可以怼面试官。
工程上对排序的改进
1)充分利用O(N*logN)和O(N^2)排序各自的优势
2)稳定性的考虑
- 样本量小于六十的时候用插入排序
- 基础类型用快速排序,非基础类型用归并排序
这篇关于左神算法-基础03的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26消息中间件源码剖析教程
- 2024-11-26JAVA语音识别项目资料的收集与应用
- 2024-11-26Java语音识别项目资料:入门级教程与实战指南
- 2024-11-26SpringAI:Java 开发的智能新利器
- 2024-11-26Java云原生资料:新手入门教程与实战指南
- 2024-11-26JAVA云原生资料入门教程
- 2024-11-26Mybatis官方生成器资料详解与应用教程
- 2024-11-26Mybatis一级缓存资料详解与实战教程
- 2024-11-26Mybatis一级缓存资料详解:新手快速入门
- 2024-11-26SpringBoot3+JDK17搭建后端资料详尽教程