小玉的字符
1 条题解
-
0
P4654 小玉的字符(入门)
解题思路
第一步,读懂题目。 小玉看到一串由小写字母组成的字符,想知道一共有多少种不同的字符,还要把不同的字符按 ASCII 码从小到大排好输出。
第二步,用标记数组去重。 开一个标记数组 marked,marked[c] 为 true 就表示字符 c 出现过。扫描一遍字符串,把每个出现过的字符都打上标记;同一个字符第二次出现时,标记已经存在,自然就不会被重复计算了。
第三步,利用 ASCII 码顺序免排序。 因为字符只可能是 a 到 z,而 ASCII 码中 a<b<c<...<z,字母的顺序就是从小到大的顺序。所以只要从 'a' 开始按字母顺序检查到 'z',凡是 marked[c] 为 true 就输出,输出结果天然就是从小到大排好序的,连排序都不用单独写。一边检查一边数出不同字符的个数 distinctCnt。
第四步,用样例验证。 拿样例 "tctm" 来说:出现的字符有 t、c、m 三种,去掉重复后按顺序是 c、m、t,所以第一行输出 3,第二行输出 cmt。注意题目数据的第二行是这些字符连着写的,中间没有空格,和题面描述的"用空格隔开"不一样,要以实际测试数据为准。
第五步,处理空输入。 和统计字符那题一样,如果输入是空串,什么都不输出。
第六步,体会"桶排序"思想。 其实这道题不需要真正写出复杂的排序代码,因为 a 到 z 的 ASCII 码本来就是从小到大排列的,我们只要按顺序扫描一遍、遇到出现过的字符就输出,就自动完成了排序,这就是"桶排序"思想的简单应用。如果字符串里出现的是其他字符,处理方式类似,但本题限定只有小写字母,问题被大大简化了,思路也更容易讲清楚。
参考代码
// P4654 小玉的字符:去掉重复字符后按 ASCII 码从小到大排序输出 #include <iostream> using namespace std; char str[1005] = ""; bool marked[128]; int main() { if (!(cin >> str)) return 0; // 输入为空时直接结束,不输出任何内容 // 标记哪些字符出现过 for (int i = 0; str[i] != '\0'; i++) marked[(int)str[i]] = true; // 统计不同字符个数,并按照 ASCII 顺序输出(数据中字符之间没有空格) int distinctCnt = 0; for (int c = 'a'; c <= 'z'; c++) if (marked[c]) distinctCnt++; cout << distinctCnt << endl; for (int c = 'a'; c <= 'z'; c++) if (marked[c]) cout << (char)c; cout << endl; return 0; }复杂度分析
扫描字符串一次 O(len),再从 'a' 到 'z' 检查 26 次,总时间 O(len+26),len 最大 1000。空间上只用一个标记数组 marked,O(1)。非常高效。
- 1