注:原题表述有误,出题者已更正。
U560289 字符串排序(一)
题目描述
输入一个字符串,长度小于等于200个字符,然后将输入的字符串按字符升序排序后输出。注意以下规则:
①26个字母按a→z顺序排序;
②一组字符串内可能有空格,直接丢弃处理;
③保证字符串只含小写字母和空格。
输入格式
第1行有1个整数n,代表着n组输入数据。
第2到n+1行,均有一组字符串。
输出格式
输出n行,每行为处理后的字符串。
输入输出样例
输入 #1
1 tian qin
输出 #1
aiinnqt
说明/提示
样例解析
字符串升序排序后应为aiinnqt。
数据范围
n≤1000,输入数据每行只有一个长度不大于200的字符串,且仅含大小写字母和空格。
参考答案
#include <iostream> #include <string.h> #include <stdio.h> using namespace std; int n,a[140]; string s; void Sort()//使用桶排序排序字符串s { for(int i=0;i<s.size();i++) { a[s[i]]++; } } void Print()//输出排序完后的结果 { for(int i=90;i<=130;i++) { for(int j=1;j<=a[i];j++) { printf("%c",i); } } cout<<endl; } int main() { cin>>n; getline(cin,s); for(int i=1;i<=n;i++) { memset(a,0,sizeof(a));//桶排序数组a赋值为零 getline(cin,s); Sort(); Print(); } return 0; }
解题思路
本题最难的部分在于给字符串排序。本题使用桶排序最为方便简单。
算法概述:
桶排序算法原理是将数组分到有限数量的桶里,再对每个桶分别排好序,最后一次将每个桶中排好序的数输出。
解题步骤:
1.用 cin 或 scanf 读入字符串行数n,再用 getline函数 读取每行的字符串。
注意 :getline函数可以读取一整行的字符(包括空格)。若 cin 或者 scanf 与getline函数连用,需要多读取一次(
getline函数
会读取直到遇到换行符,并丢弃换行符,cin
会留下换行符在缓冲区,两者连用可能会导致输入错误)。2 .用桶排序给字符串排序。
本文中的参考代码中考虑空间足够,索性直接开了一个140个元素的整型数组a用来存储a下标对应ASCII码字符在字符串中出现的个数。(空格的ASCII码为32)。
3.用for循环遍历数组a,输出a的下标所对应ASCII码代表的字符,并输出对应个字符。
4.每次循环开始用 memset函数把数组a赋值为0。
U560136 字符串排(二)
题目背景
【题干与《字符串排序(一)》基本一致,仅规则②③和样例有所不同】
题目描述
输入一个字符串,长度小于等于200个字符,然后将输入的字符串按字符升序排序后输出。注意以下规则:
①26个字母按a→z顺序排序;
②可能会有大写字母,其顺序比对应小写字母靠后,如a→A→b→B→...→z→Z。
③一组字符串内可能有空格,需要替换为'&',并在原位置输出
输入格式
第1行有1个整数n,代表着n组输入数据。
第2到n+1行,均有一组字符串。
输出格式
输出n行,每行为处理后的字符串。
输入输出样例
输入 #1
1 TiAn qiN
输出 #1
Aiin&NqT
说明/提示
样例解析
字符串升序排序后应为AiinNqT,原第五个字符位有空格,因此答案为Aiin&NqT。
数据范围
n≤1000,输入数据每行只有一个长度不大于200的字符串,且仅含大小写字母和空格。
参考答案
#include <bits/stdc++.h> using namespace std; bool cmp(char a,char b) { if(tolower(a)!=tolower(b)) { return tolower(a)<tolower(b); //先按字母表顺序排序(不区分大小写) } return a>b; //同一字母:小写字母排在大写字母前面 } int main() { int n; cin>>n; cin.ignore(); //忽略换行符 while(n--) { string s; getline(cin,s); //读入整行字符串(包含空格) string t(s.size(),' '); //创建与s等长的字符串,初始为空格 for(int i=0;i<s.size();i++) { if(s[i]==' ')t[i]='&'; //空格位置替换为& } sort(s.begin(),s.end(),cmp); //按自定义规则排序 int i=0; //跳过排序后开头的空格(排序后空格集中在前面) while(i<s.size()&&s[i]==' ')i++; for(int j=0;j<t.size();j++) { if(t[j]=='&')continue; //跳过标记的&位置 t[j]=s[i++]; //非空格位置填入排序后的字符 } cout<<t<<endl; //输出结果 } return 0; }
解题思路 (代码解析)
解题步骤:
1.读入字符串数量
**cin.ignore()作用:
cin >> n
读取整数后,输入缓冲区会残留一个换行符'\n'
若不忽略,后续的getline()
会立即读到空行
cin.ignore()
默认忽略1个字符(正好是残留的换行符)2.空格处理
**
getline()
读取整行(包括空格)创建临时字符串
t
,在原始空格位置标记'&'其他位置暂时保留空格(后续会被覆盖)
3.调用自定义比较函数
当字母不同 时(忽略大小写),按字母表升序排序
当是同一字母时(如'a'和'A'):
小写字母(ASCII码值大)排在大写字母前面(ASCII码值小)
实现题目要求的排序规则:a→A→b→B→...→z→Z
4 .排序与空格跳过
空格在ASCII表中(输入数据的数据中)值最小,排序后会集中在字符串开头
循环跳过所有空格,
i
指向第一个非空格字符5.结果组装输出
++遍历临时字符串
t
++:
遇到'&':保持原样(对应原始空格位置)
其他位置:依次填入排序后的非空格字符
++最终得到++:原空格位置显示'&',其他位置显示排序后的字符
创作历时1.5小时,感谢阅读!