【正确答案】如果没有时间复杂度的要求,本题可以采用传统的插入排序或快速排序等方法进行排序,但是传统的排序方法在最好的情况下的时间复杂度都为O(nlogn),显然,不满足题目要求的O(n)时间复杂度。对于对时间复杂度有很高要求的问题,一般可以考虑用空间换时间的方法。鉴于此,对于本题而言,可以采用如下思路:
通常,字母为26个,当区分大小写后,变为26*2=52个,所以,首先申请一个长度为52的int型数组,按照aAbBcC...zZ(小写字母保存在下标为偶数的位置,大写字母保存在下标为奇数的位置)的顺序依次记录各个字母出现的次数,当记录完成以后,就可以遍历这个数组按照各个字母出现的次数来重组排序后的数组,实现代码如下:
public class Test{
public static void main(String[]args) {
char[]src={'R','B','B','b','W','W','B','R','B','w'};
sort(src);
for(int i=0;i<src.length;i++){ System.out.print(src[i]+" ");}
}
private static void sort(char[]src) {
if(src==null) {
System.out.pIintln("参数不合法");
return;
}
//用于保存52个字符出现的次数,小写字母保存在下标为偶数的位置,大写字母保存在奇
//数的位置
//采用这种保存方法,可以保证在这个数组中小写字母出现在大写字母前面,小的字符出现
//在大的字符前面
int[]charCount=new int[54];
for(int i=0;i<src.length;i++) {
//对小写字母出现的次数就行计数
if(src[i]>'a'&&src[i]<'z'){charCount[(src[i]-'a')*2]++;}
//对大写字母出现的次数就行计数
else if(src[i]<'Z'&&src[i]>'A') {charCount[(src[i]-'A')*2+1]++;}
}
//根据各个字符出现的次数按顺序生成排序后的字符数组
int index=0;
for(int i=0;i<charCount.length;i++) {
//这个字符在原始字符数组中存在
if(charCount[i]!=0){
//小写字母
if(i%2==0) {
for(int j=0;j<charCount[i];j++){
src[index++]=(char)(i/2+'a');
}
}
//大写字母
else{
for(int j=0;j<charCount[i];j++){
src[index++]=(char)((i-1)/2+'A');
}
}
}
}
}
}
程序的运行结果为:
b B B B B R R w W W
【答案解析】