出现次数最多的小写字母

该博客讨论如何在C++中找到输入字符串中出现次数最多的小写字母。当有多个字母出现频率相同时,应返回ASCII码值最大的字母。样例输入为'aaabbbbbbbbbcdxs',输出为'b'。

出现次数最多的小写字母

题目描述
输入一个由小写字母组成的字符串(字符数量<=100),输出出现次数最多的小写字母。
注意:如果有多个小写字母出现的次数一样多,则输出ASCII码值最大的那个字母。

输入
一个字符串
输出
出现次数最多的小写字母
样例输入复制
aaabbbbbbbbbcdxs
样例输出复制
b

#include<bits/stdc++.h>
using namespace std;
int a[200];
string s;
int main
<think> 我们参考了多个引用,这些引用都展示了在C语言中找出字符串中出现次数最多字母的方法。核心思路是: 1. 定义一个长度为26的整型数组(对应26个英文字母)用于计数。 2. 遍历输入字符串的每个字符,将字符映射到计数数组的相应位置(例如,'a'对应0,'b'对应1,...,'z'对应25),然后增加该位置的计数。 3. 在遍历的同时,记录当前的最大次数以及对应的字母(或者记录最大次数对应的索引,然后映射回字母)。 4. 注意:题目要求是小写字母,但引用[4]也考虑了大小写的情况(将大写字母转换为小写字母处理)。但根据问题描述,输入全部由小写字母组成,因此可以只处理小写字母。 根据引用[1]、[2]、[3]、[4]的代码,我们可以总结出以下步骤: 步骤1:定义一个计数数组(大小为26),并初始化为0。 步骤2:读入字符串(注意:引用[1]和[2]使用循环读入多组数据,直到文件结束)。 步骤3:遍历字符串中的每个字符,如果是小写字母,则将其转换为索引(通过减去字符'a'),然后增加计数数组对应位置的值。 步骤4:在遍历过程中,可以同时记录最大次数和对应的字符(或索引)。或者,也可以先遍历完字符串,再遍历计数数组找出最大值。 步骤5:输出出现次数最多的字母(如果有多个字母出现次数相同且都是最大值,通常题目要求输出任意一个即可,但根据样例输出,只输出一个。引用[1][2]在遍历过程中记录第一个达到最大值的字母,而引用[4]则是在最后遍历计数数组,并输出第一个最大值对应的字母)。 注意:如果字符串中同时存在大小写字母,我们可以统一转换为小写或大写后再计数。但题目明确输入全部为小写字母,所以可以不做转换。 我们参考引用[2]的代码,因为它更简洁清晰: ```c #include <stdio.h> #include <string.h> int main() { char input[101]; // 假设字符串长度不超过100 while (scanf("%s", input) != EOF) { // 多组输入直到文件结束 int count[26] = {0}; // 初始化计数数组为0 int maxCount = 0; // 记录最大次数 char maxChar; // 记录出现次数最多的字母 // 遍历字符串 for (int i = 0; i < strlen(input); i++) { // 因为输入都是小写字母,所以可以直接减去'a'得到0-25的索引 int index = input[i] - 'a'; count[index]++; // 对应字母计数加1 // 如果当前字母的计数大于最大计数,则更新 if (count[index] > maxCount) { maxCount = count[index]; maxChar = input[i]; } } printf("%c\n", maxChar); } return 0; } ``` 但是,上述代码有一个小问题:如果出现多个字母出现次数相同且都是最大值,那么它会输出最后一次更新maxChar的那个字母(即最后出现的达到最大次数的字母)。而题目要求是输出出现次数最多的那个字母,如果多个字母出现次数相同,题目没有明确要求,但样例输出只要求输出一个。因此,我们可以输出任意一个最大值对应的字母。 然而,引用[1]的代码是记录最大值的索引,然后通过一个字母表数组(ch[27])来输出字母。引用[1]在遍历过程中记录的是第一个达到最大值的字母(因为一旦当前字母的个数超过当前最大值就更新,所以第一次达到最大值时更新,后续如果出现更大的再更新,但如果出现和最大值一样的则不会更新,所以最后记录的是最后一次更新时的最大值对应的字母)。 如果我们希望输出第一个出现次数最多的字母(即遇到第一个最大值就记录下来,后续即使有同样次数的也不更新),那么可以在更新条件上改为“大于等于”来记录最后一个,但这样会记录最后一个出现次数最多的字母。或者,我们可以在遍历完整个字符串后再去遍历计数数组,这样我们可以输出第一个出现次数最多的字母(即按字母序最小的那个最大值字母)?但是题目没有要求,所以两种方式都可以。 根据问题描述,样例输入和输出: 输入:aaaaaaabbc -> 输出:a 输入:nnnnnnnasnnnnasaaaa -> 输出:n 在第二个样例中,a和n都出现了多次,但是n的次数比a多(因为输入中n有10个,a有5个),所以输出n。因此,我们只需要输出出现次数最多的那个字母(即使有并列,题目没有说明,但样例中并没有并列最大值的情况)。所以,我们按照上述方法即可。 但是,如果出现并列最大值,比如"aabb",那么a和b都出现两次,上述代码会输出后达到最大值的那一个(即b)。如果我们希望输出按字母序最小的那个,那么就需要在遍历计数数组时按顺序找最大值,然后输出第一个最大值对应的字母(即a)。 题目要求:找出出现次数最多的那个字母(一个)。因此,如果出现并列,可以输出任意一个,但题目没有明确要求。从样例输出看,并没有并列的情况,所以我们可以按照任意一个输出。 为了与样例一致,我们采用上述引用[2]的方法(即输出最后遇到的最大值对应的字母)即可。但如果我们想要输出字母序最小的那个,可以在遍历完计数数组后,再遍历一次计数数组(从0到25,即从a到z),找到第一个等于最大值的字母。 修改后的版本(输出字母序最小的那个最大值字母): ```c #include <stdio.h> #include <string.h> int main() { char input[101]; while (scanf("%s", input) != EOF) { int count[26] = {0}; int maxCount = 0; // 先遍历字符串,统计每个字母出现的次数,并记录最大次数 for (int i = 0; i < strlen(input); i++) { int index = input[i] - 'a'; count[index]++; if (count[index] > maxCount) { maxCount = count[index]; } } // 然后按字母序(a~z)遍历计数数组,找到第一个出现次数等于maxCount的字母 for (int i = 0; i < 26; i++) { if (count[i] == maxCount) { printf("%c\n", 'a' + i); break; // 找到第一个就退出 } } } return 0; } ``` 这样,在出现并列最大值时,会输出字母序最小的那个。例如,对于"aabb",会输出'a'。 根据问题,用户没有特别要求并列的情况,所以两种实现都可以。我们可以根据实际需求选择。 总结:C语言中找出出现次数最多字母的方法,主要是使用计数数组,然后遍历字符串统计,最后找到最大值对应的字母。 注意:输入全部为小写字母,所以不考虑大写。 我们选择第一种方法(即引用[2]的方法)作为示例,因为它只需要遍历一次字符串,并且在遍历过程中就记录了最大值对应的字母,效率较高。 但是,如果字符串很长,我们可能希望在一次遍历中完成,并且还要处理并列时输出字母序最小的,那么可以在更新最大值时增加条件:如果当前字母的计数大于最大值,则更新;如果等于最大值,那么判断当前字母是否比之前记录的最大值字母的字母序小,如果是则更新(但这样会输出最后一个字母序最小的最大值字母?实际上,我们遍历字符串的顺序不是按字母序,所以无法保证输出第一个出现的字母序最小的那个)。因此,为了确保输出字母序最小的,最好还是使用第二种方法:先遍历字符串统计,然后按字母序遍历计数数组。 根据引用[3]和[4]的提示,我们也可以采用建立镜像数组的方式。 考虑到用户的问题没有明确要求并列的情况,我们给出两种方法,并说明其区别。 方法一:一次遍历,同时记录最大值和对应的字母(输出的是最后一次更新最大值的字母) 方法二:先统计,再按字母序查找(输出的是字母序最小的那个最大值字母) 在实际问题中,题目要求是“找出出现次数最多的那个字母”,通常没有特别要求,所以两种方法都可行。 下面我们分别给出两种方法的代码: 方法一(输出最后更新的最大值字母): ```c #include <stdio.h> #include <string.h> int main() { char str[110]; while (gets(str) != NULL) { // 或者使用scanf,但注意gets和scanf的区别,gets读取一行,scanf遇到空格会停止 int count[26] = {0}; int max = 0; char maxChar = 'a'; // 初始化为'a' int len = strlen(str); for (int i = 0; i < len; i++) { int index = str[i] - 'a'; count[index]++; if (count[index] > max) { max = count[index]; maxChar = str[i]; } } printf("%c\n", maxChar); } return 0; } ``` 注意:这里使用gets是不安全的,因为可能超过数组长度。推荐使用fgets或者scanf限定宽度。但由于题目说明不超过100个字符,数组定义为110,所以可以用gets。但注意,C11标准中移除了gets,所以更推荐使用fgets。 修改为fgets: ```c #include <stdio.h> #include <string.h> int main() { char str[110]; while (fgets(str, sizeof(str), stdin) != NULL) { // 注意:fgets会读入换行符,我们需要去掉吗?因为题目输入是连续的小写字母,可能没有空格,但可能有换行?题目没有明确,但样例输入是一行,所以换行符需要处理。 // 去掉换行符 size_t len = strlen(str); if (len > 0 && str[len-1] == '\n') { str[len-1] = '\0'; } int count[26] = {0}; int max = 0; char maxChar = 'a'; len = strlen(str); for (int i = 0; i < len; i++) { int index = str[i] - 'a'; if (index < 0 || index > 25) continue; // 确保是小写字母,但题目说了是小写字母,可以省略 count[index]++; if (count[index] > max) { max = count[index]; maxChar = str[i]; } } printf("%c\n", maxChar); } return 0; } ``` 方法二(输出字母序最小的最大值字母): ```c #include <stdio.h> #include <string.h> int main() { char str[110]; while (fgets(str, sizeof(str), stdin) != NULL) { size_t len = strlen(str); if (len > 0 && str[len-1] == '\n') { str[len-1] = '\0'; } int count[26] = {0}; int max = 0; int len_str = strlen(str); for (int i = 0; i < len_str; i++) { int index = str[i] - 'a'; if (index < 0 || index > 25) continue; count[index]++; if (count[index] > max) { max = count[index]; } } // 按字母序从a到z遍历 for (int i = 0; i < 26; i++) { if (count[i] == max) { printf("%c\n", 'a' + i); break; } } } return 0; } ``` 用户可以根据需求选择其中一种方法。 注意:在方法二中,我们内层循环从0到25(即a到z),所以第一个等于最大值的字母就是字母序最小的那个。 以上就是在C语言中找出出现次数最多字母的两种实现方法。 最后,我们生成相关问题: §§相关问题§§ 1. 如果字符串中同时包含大写和小写字母,如何统计出现次数最多的字母(不区分大小写)? 2. 如果出现次数最多的字母有多个,要求输出所有出现次数最多的字母,应该如何修改代码? 3. 如何优化这段代码的性能(例如,对于非常长的字符串)? </think> ### C语言中找出出现次数最多字母的实现方法 在C语言中,找出字符串中出现次数最多的字母主要通过**计数数组**实现。以下是详细步骤和两种实现方法(均支持多组输入): #### 核心思路 1. **定义计数数组**:创建长度为26的数组`count[26]`,对应26个小写字母(索引0='a', 1='b', ..., 25='z')。 2. **遍历字符串**:对每个字符: - 计算索引值:`index = 字符 - 'a'` - 计数数组对应位置加1:`count[index]++` 3. **记录最大值**:在遍历过程中动态更新最大次数及其对应字母。 4. **处理多组输入**:使用`while(scanf(...) != EOF)`或`while(gets(...) != NULL)`。 --- ### 方法一:动态更新最大值(推荐) 边统计边记录最大值,效率较高: ```c #include <stdio.h> #include <string.h> int main() { char input[101]; while (scanf("%s", input) != EOF) { // 多组输入 int count[26] = {0}; // 初始化计数数组 int maxCount = 0; char maxChar = 'a'; // 默认输出'a' for (int i = 0; i < strlen(input); i++) { int index = input[i] - 'a'; // 字符映射到0-25 count[index]++; // 动态更新最大值 if (count[index] > maxCount) { maxCount = count[index]; maxChar = input[i]; // 记录当前最大字符 } } printf("%c\n", maxChar); } return 0; } ``` --- ### 方法二:先统计后查找 先完成全部计数,再遍历数组找最大值: ```c #include <stdio.h> #include <string.h> int main() { char str[110]; while (gets(str) != NULL) { // 读入一行 int count[26] = {0}; int max = 0; // 1. 统计字母出现次数 for (int i = 0; i < strlen(str); i++) { if (str[i] >= 'a' && str[i] <= 'z') { count[str[i] - 'a']++; } } // 2. 找出最大次数 for (int i = 0; i < 26; i++) { if (count[i] > max) max = count[i]; } // 3. 输出第一个达到最大值的字母 for (int i = 0; i < 26; i++) { if (count[i] == max) { printf("%c\n", 'a' + i); // 索引转字母 break; // 只输出第一个 } } } return 0; } ``` --- ### 关键点说明 1. **索引计算**:`字符 - 'a'`将字母映射到0-25(如`'c' - 'a' = 2`)。 2. **效率对比**: - 方法一:只需单次遍历,时间复杂度$O(n)$。 - 方法二:需三次遍历(统计、找最大值、输出),但逻辑更清晰。 3. **多组输入**:`scanf("%s", input) != EOF`或`gets(str) != NULL`确保持续读入数据。 4. **边界处理**:输入不超过100字符,数组长度需≥101(预留结束符`\0`)。 > 示例输入: > `aaaaaaabbc` → 输出:`a` > `nnnnnnnasnnnnasaaaa` → 输出:`n`[^1][^2] --- ### 注意事项 - **大小写敏感**:示例代码假设输入全小写字母,若含大写需转换(`str[i] = tolower(str[i])`)。 - **并列最大值**:上述代码输出**第一个**出现次数最多的字母(如`aabb`输出`a`),如需输出全部需额外处理。 - **输入安全**:使用`fgets`替代`gets`避免溢出(如`fgets(str, sizeof(str), stdin)`)。 ---
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值