1、桶排序、计数排序、基数排序不是基于比较的排序,与被排序的样本的实际数据状况很有关系,所以实际中并不经常使用。计数排序是桶排序的一个实际应用。
2、时间复杂度O(N),额外空间复杂度O(N)
3、稳定的排序
例子:给你一个数组,数组中的所有数的范围是0~60的,把这个数组排好序。
做法:生成一个长度为61的(词频)数组,初始化数组为{0,0,…,0}。然后遍历原数组,遇到一个数的时候,在该数对应词频数组下标的位置++,表示词频加1。比如初始数组为{2,1,3,7,1,0,5,4,6,6,1,1,2,0}对应的词频数组是{2,4,2,1,1,1,2,1},这样就可以通过词频数组去重建整个数组为{0,0,1,1,1,1,2,2,3,4,5,6,6,7}。时间复杂度为O(N)。
面试常考问题:给定一个数组,求如果排序之后,相邻两个数的最大差值,要求时间复杂度O(N),且要求不能用非基于比较的排序。
做法:
1)准备桶。若有N个数,就准备N+1个桶。0号桶,1号桶,…,N号桶。每个桶只记录出现在这个桶的数的最小值和最大值以及这个同是否进来过数。
2)从1号桶开始,如果他是空桶,则直接跳下一个数,如果它是非空桶,则找前一个非空桶,对于后面的任何一个非空桶,要找这个非空桶左边离它最近的非空桶,他左边离它最近的非空桶的最大值max和它当前这个非空桶的最小值min,算一下差值,我们要求的最大差值一定在这些答案中间是最大的。
注意:我们设计空桶的分析方式就是为了否定最大差值来自一个桶内部的可能性,但我们没说过最大差值一定来自于空桶两侧的非空桶。
public class Test{
public static int maxGap(int[] arr){
if(arr==null||arr.length<2) {
return 0;
}
int min=Integer.MAX_VALUE;
int max=Integer.MIN_VALUE;
for(int i=0;i<arr.length;i++) {//遍历数组找出数组的最大值和最小值
min=Math.min(min, arr[i]);
max=Math.max(max, arr[i]);
}
if(max==min) {//数组只有一种数的情况
return 0;
}
//下面3个数组表示0~N号桶的3个信息
boolean[] hasNum=new boolean[arr.length+1];
int[] maxs=new int[arr.length+1];
int[] mins=new int[arr.length+1];
int bid=0;
for(int i=0;i<arr.length;i++) {
bid=bucket(arr[i],arr.length,min,max);//确定当前数属于几号桶
//数字进入桶之后,相应的最大值,最小值,hasNum标志等都要相应变化
mins[bid]=hasNum[bid]?Math.min(mins[bid], arr[i]):arr[i];
maxs[bid]=hasNum[bid]?Math.max(maxs[bid], arr[i]):arr[i];
hasNum[bid]=true;
}
int res=0;//全局最大差值
int lastMax=maxs[0];//初始化lastMax为0号桶的最大值
int i=1;
for(;i<=arr.length;i++) {//从1号桶开始找到每一个非空桶和左边离它最近的非空桶,用当前桶最小值-前一个非空桶的最大值=res
if(hasNum[i]) {//若桶不为空
res=Math.max(res, mins[i]-lastMax);//比较当前res与当前桶最小值与前一个非空桶的最大值的差值,取最大值赋值给res
lastMax=maxs[i];//当前非空桶的最大值赋值给lastMax,继续进行下一轮遍历
}
}
return res;
}
//确定当前数属于几号桶
public static int bucket(long num,long len,long min,long max) {
return (int)((num-min)*len/(max-min));
}
public static void main(String[] args) {
int[] arr= {6,3,4,3,1,3,9,5};
System.out.println(maxGap(arr));
}
}
输出:3
import java.util.Arrays;
public class Test{
public static int comparator(int[] arr) {
if(arr==null||arr.length<2)
return 0;
Arrays.sort(arr);
int gap=Integer.MIN_VALUE;
for(int i=1;i<arr.length;i++) {
gap=Math.max(arr[i]-arr[i-1], gap);
}
return gap;
}
public static void main(String[] args) {
int[] arr= {6,3,4,3,1,3,9,5};
System.out.println(comparator(arr));
}
}
输出:3