题目要求:
编写一个程序,将输入字符串中的字符按如下规则排序。
规则 1 :英文字母从 A 到 Z 排列,不区分大小写。
规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。
规则 3 :非英文字母的其它字符保持原来的位置。
解读:要求升序排序、排序算法是稳定的、忽略非字母字符
思路及代码如下:
Python版本:
# 思路:类似于冒泡排序的思路 # 注意:这里有个坑,就是要求:同一个字母的大小写的相对位置要与输入时一致 # 这实际上就是在要求排序算法是稳定的,所以不能使用选择排序或者快排等不稳定的排序方法 # 我一开始就是用的选择排序,结果测试样例里面的S和s顺序颠倒了 # 新坑:冒泡的原理是对相邻元素进行排序,但是此题不允许对非字母字符排序, # 这就导致冒泡时一旦遇到非字母字符就会终止冒泡,所以传统冒泡在这里直接g了 # 解决:采取动态步长,重新定义“相邻” a = list(input()) for i in range(0, len(a) - 1): for j in range(0, len(a) - i - 1): if "a" <= a[j] <= "z" or "A" <= a[j] <= "Z": # 对于前一个元素,必须要求为字母 for buchang in range(1, len(a) - j): # 步长可变,使用a[j+buchang]表示与a[j]相邻的字母 if not ( "a" <= a[j + buchang] <= "z" or "A" <= a[j + buchang] <= "Z" ): # 对于后一个元素,如果不是字母就跨过他,即将buchang增加1 continue else: # 是字母,下面无论是否发生交换都要结束for循环了 if a[j].lower() > a[j + buchang].lower(): # 交换 temp = a[j + buchang] a[j + buchang] = a[j] a[j] = temp break # 注意这里找到了“相邻”元素,交换之后就得跳出for循环了 else: break # 这个break也很重要,只要a[j+buchang]是一个字母,那么无论是否发生交换, # 都要结束for循环,如果不加这个break,这个冒泡就会不稳定 b = "".join(a) print(b)
C++版本:
//思路:类似于冒泡排序的思路 //注意:这里有个坑,就是要求:同一个字母的大小写的相对位置要与输入时一致 //这实际上就是在要求排序算法是稳定的,所以不能使用选择排序或者快排等不稳定的排序方法 //我一开始就是用的选择排序,结果测试样例里面的S和s顺序颠倒了 // //新坑:冒泡的原理是对相邻元素进行排序,但是此题不允许对非字母字符排序, //这就导致冒泡时一旦遇到非字母字符就会终止冒泡,所以传统冒泡在这里直接g了 //解决:采取动态步长,重新定义“相邻” #include<bits/stdc++.h> using namespace std; int main(){ char s[1001]; cin.get(s,1001); for(int i=0;i<strlen(s)-1;i++){ for(int j=0;j<strlen(s)-i-1;j++){ if('a'<=s[j]&s[j]<='z' || 'A'<=s[j]&s[j]<='Z'){ for(int buchang=1;buchang<strlen(s)-j;buchang++){ if(!('a'<=s[j+buchang]&s[j+buchang]<='z' || 'A'<=s[j+buchang]&s[j+buchang]<='Z')) continue; else{ if(tolower(s[j])>tolower(s[j+buchang])){ char temp=s[j]; s[j]=s[j+buchang]; s[j+buchang]=temp; break; } else break; } } } } } // 输出 for(int i=0;i<strlen(s);i++){ cout<<s[i]; } return 0; }