非比较排序:桶排序、计数排序、 基数排序
桶排序对应的很多都是困难题哦;
- 非基于比较的排序,与被排序的样本的实际数据状况很有关系,所以实际中并不经常使用
- 时间复杂度0(N),额外空间复杂度0(N)
- 稳定的排序
非比较排序引例
例子:对0-60的数组进行排序
- 遍历数组,进行数组频数统计,然后就可以重构出排序结果。可以看出是不基于比较,而是基于桶(桶就是一个容器,就是一个数出现的频次)
- 桶排序是一个大概念,上面的是计数排序,是桶排序的一个具体实现
例子:对应leetcode-164
给定一个数组,求如果排序之后,相邻两数的最大差值,要求时间复杂度0(N),且要求不能用非基于比较的排序
- 桶划分的逻辑:
有9个数,则划分为10个桶;根据最大值和最小值划分为10个范围;每个数进入对应的范围;
最大值是99,最小值是0,则划分为下面范围的桶;里面的是每个桶对应的范围
- 因为有N个数,而有N+1个桶;最大数和最小数都在两端的桶;那么中间的桶一定有一个空桶;那么最大的差值就空桶左边桶的最大值和右边桶最小值。
- 每个桶需要记录的元素:是否有数据、最大值、最小值
public int maximumGap(int[] nums) {
if (nums == null || nums.length < 2) return 0;
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
int len = nums.length;
for (int i = 0; i < len; i++) {
max = Math.max(max, nums[i]);
min = Math.min(min, nums[i]);
}
if (max == min) {
return 0;
}
boolean[] hasNum = new boolean[len+1];
int[] maxs = new int[len+1];
int[] mins = new int[len+1];
int bid = 0; //表示桶的位数
for (int i = 0; i < len; i++) {
// 确定当前数属于几号桶
bid = bucket(nums[i], len, min, max);
mins[bid] = hasNum[bid] ? Math.min(mins[bid], nums[i]) : nums[i];
maxs[bid] = hasNum[bid] ? Math.max(maxs[bid], nums[i]) : nums[i];
hasNum[bid] = true;
}
int res = 0;
int lastMax = maxs[0];
int i = 1;
for (; i <= len; i++) {
if (hasNum[i]) {
res = Math.max(res, mins[i] - lastMax);
lastMax = maxs[i];
}
}
return res;
}
public int bucket(long num, long len, long min, long max) {
return (int) ((num - min) * len / (max-min));
}