论述题 2.  实现对一组无序的字母进行从小到大排序(区分大小写),当两个字母相同时,小写字母放在大写字母前。要求时间复杂度为O(n)。
【正确答案】如果没有时间复杂度的要求,本题可以采用传统的插入排序或快速排序等方法进行排序,但是传统的排序方法在最好的情况下的时间复杂度都为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
【答案解析】