1、排序算法的稳定性及其总结
对于数组中相同的数,在排序后还能不能保持相对位置不变,比如1112233344445,虽然是一样的,但是希望相对位置不要变
- 冒泡排序稳定
- 插入排序稳定
- 选择排序不稳定
- 归并排序稳定(先排左区,再排右区,可以做到稳定)
- 快排不稳定(4443 — 3444)(也就是说parttion过程做不到小于一个数放左边,然后这些数相对次序还不变)
- 堆排不稳定(44455,heapInsert的时候,稳定性会被破坏)
在数据量小于60的时候,会用插入排序(常数量小),当数据量大的时候,基础类型快排(快排不稳定),自定义类型归并排序(归并稳定,归并排序切分的时候,数据量小于60,还是会用插排)
补充:
- 原地归并排序可以空间复杂度为O(1),但是时间复杂度变成了O(N^2),不要考虑这种
- 快排的优势之一:空间复杂度O(1),parttion时间复杂度最差O(N)(荷兰国旗问题)
2、桶排序
时间复杂度O(N),额外空间复杂度O(N),稳定
桶排序不是基于比较的排序,与被排序的样本的实际数据状况有关,所以实际中并不经常使用,桶排序是一个大的逻辑概念,桶可以是很多东西,如双向链表,数组等
桶排序有两个体现:
- 计数排序:如以词汇出现频率排序的词频排序
- 基数排序:改进了计数排序,以数的区域划分桶的接收范围
练手题目:
给定一个数组,求排序之后,相邻两数的最大差值,要求时间复杂度O(N),且要求不能用非基于比较的排序
这里借用桶的概念,但是没有进行桶排序
步骤:
- 找到数组中的最大最小值,这里可以用Integer的MAX属性,很有意思
- 建立三个len+1长度的数组(即桶,分别存放桶中是否有数hasNum、最大值maxs、最小值mins)
- 遍历数组,将数放到桶里(只放最大值/最小值和是否有值,这里需要知道一个数在哪个桶中)
- 遍历桶,找到相邻的非空桶的间隔最大(min - lastMAX)
注意:这里有len+1个桶,其中第0个和最后一个即第len个桶肯定有最小和最大值
关于下面的代码,有两个问题可能会有疑惑:
- 下面的两个代码一样么?
int min = Integer.MIN_VALUE;
int max = Integer.MAX_VALUE;
for (int i = 0; i < len; i++) {
min = Math.min(arr[i], max);
max = Math.max(arr[i], min);
=================不一样,下面的是正确的,上面的变量min和max混乱了========