一、算法思想
针对整数序列(包括负数),创建待排序数组最大值+1的辅助数组,
根据待排序数组值找到对应辅助数组下标,让对应下标值+1,最终
扫描辅助数组获得排序结果。
解决负数问题
- 同整=正数一样开辟一个辅助空间,空间大小为最小数(负数)(兼容正数)的绝对值+1,在计数时判断正负进入不同的辅助数组,其中负数辅助数组用绝对值代替,在输出时,先从大到小输出负数辅助数组(切记*-1)在输出正数辅助数组。
算法优势:
- 时间复杂度低O(n);
算法劣势:
- 对于稀疏数列,浪费空间;
二、代码实现
public static void main(String[] args) {
int[] arr={12,4,3465,123,3,346,2,13,235,3,462,462,76};
int[] arr2={-100,-1,12,4,3465,123,3,346,2,13,235,3,462,462,76};
//Arrays.sort(arr);
countSort(arr);
printArr(arr);
//测试负数
countSort2(arr2);
printArr(arr2);
}
//解决有负数问题
private static void countSort2(int[] arr) {
int max= maxOf(arr);
int min=minOf(arr);
int[] helperMax=new int[max+1];
int[] helperMin=new int[Math.abs(min)+1];
for (int i = 0; i <arr.length ; i++) {
if(arr[i]>=0){
helperMax[arr[i]]++;
}else {
helperMin[Math.abs(arr[i])]++;
}
}
int t=0;
for (int i= helperMin.length-1; i >=0 ; i--) {
while (helperMin[i]!=0){
arr[t++]=i*(-1);
helperMin[i]--;
}
}
for ( int i = 0; i <helperMax.length; i++) {
while (helperMax[i]!=0){
arr[t++]=i;
helperMax[i]--;
}
}
}
//适用于重复和正整数
private static void countSort(int[] arr) {
int max= maxOf(arr);
int[] helper=new int[max+1];
for (int i = 0; i <arr.length ; i++) {
helper[arr[i]]++;
}
for (int i = 0,t=0; i <helper.length; i++) {
while (helper[i]!=0){
arr[t++]=i;
helper[i]--;
}
}
}
public static int minOf(int[] arr){
int min=arr[0];
for (int i = 1; i <arr.length ; i++) {
if(min>arr[i]){
min=arr[i];
}
}
return min;
}
public static int maxOf(int[] arr){
int max=arr[0];
for (int i = 1; i <arr.length ; i++) {
if(max<arr[i]){
max=arr[i];
}
}
return max;
}
public static void printArr(int[] arr){
StringBuilder sb=new StringBuilder("[ ");
for (int i = 0; i <arr.length ; i++) {
sb.append(arr[i]+" ");
}
sb.append("]");
System.out.println(sb.toString());
}