- 我们获取到最大的数的位数
- 遍历每个数的某一位的(个位或者十位等)位数,将该位数的数字放入一个数组计数器中,计算该数出现了多少次,每个位置上的数字就代表了该数字出现了几次,比如2位置上的数为1,代表2出现了依次,然后求该数组的前缀和,前缀和就是i位置上的数是前面所有位置上的数的和加上自己位置上的数,举个例子,如图:

在求完前缀和过后,我们数组中的数就变成了小于等于i的数出现了几次。 - 将我们的数放入帮助数组之中,放在哪个位置,首先倒着遍历原来的数组,为什么要倒着,等一下解释,先看如何放,每当遍历到一个数过后获取它的那一位的数(个位或者十位等),获取到这个数过后,取我们之前创建的存放前缀和的数组找出它这个位置对应的数,如果这个数为2那么代表在这一位上小于等于该数的数量是2个,那么将该数的真正的数存放在帮助数组的位数减一的位置,可能有点难以理解,看图:

下面我们来解释为什么每次都需要倒序寻找数组,如果我们正序循环数组,当寻找个位时候并不会出错,但是当我们寻找十位上的数的时候,升序放入数组的话,我们放入结果数组的时候是从后面开始放着走的,那么会出现数字放反的情况,因为我们的前缀和只知道小于等于它的数的总数,也就是说只知道末位置,并不知道首位置(当然你也可以自己求,但是没必要又去算一次)。如图:

public static int maxBits(int arr[]){
int max=Integer.MIN_VALUE;
for(int i=0;i<arr.length;i++){
max= max<arr[i]?arr[i]:max;
}
int res=1;
while(max>=10){
max/=10;
res++;
}
return res;
}
public static void RadixSort(int arr[],int left,int right,int digit){
int length=right-left+1;
int arrHelp[]=new int[length];
for(int i=0;i<digit;i++){
int[] nums=new int[10];
for(int j=left;j<=right;j++){
int k=getNum(arr[j],i);
nums[k]++;
}
for(int j=1;j<10;j++){
nums[j]=nums[j]+nums[j-1];
}
for(int j=right;j>=left;j--){
int k=getNum(arr[j],i);
arrHelp[nums[k]-1]=arr[j];
nums[k]--;
}
for(int j=left,k=0;j<=right;j++,k++){
arr[j]=arrHelp[k];
}
}
}
public static int getNum(int num,int index){
return (num/((int)Math.pow(10, index)))%10;
}