HJ59 找出字符串中第一个只出现一次的字符

该程序用于找出输入字符串中第一个只出现一次的字符。它使用哈希映射来统计每个字符的出现次数,遍历两次字符串,第一次初始化计数,第二次找出第一个计数为1的字符并输出。若所有字符均重复或未找到单次出现的字符,则输出-1。

描述

找出字符串中第一个只出现一次的字符 

数据范围:输入的字符串长度满足 1≤n≤1000 1≤n≤1000 

输入描述:

输入一个非空字符串

输出描述:

输出第一个只出现一次的字符,如果不存在输出-1

示例1

输入:

asdfasdfo

复制输出:

o

复制

#include <iostream>
#include<map>
using namespace std;




int main() {
    string s;


    while(cin>>s){
         map<char,int> mp;
         for(int i=0;i<s.size();i++){
            mp[s[i]]=0;
        }
        if(s.size()>=1&&s.size()<=1000){
            for(int i=0;i<s.size();i++){
                for(int j=0;j<s.size();j++){
                    if(s[i]==s[j])mp[s[i]]++;
                }
            }
            for(int k=0;k<s.size();k++){
                if(mp[s[k]]==1){
                    cout<<s[k]<<endl;
                    break;
                }
                else if(k==s.size()-1 && mp[s[k]]!=1){
                    cout<<"-1"<<endl;
                }
            }
            //cout<<"-1"<<endl;
        }
    }
}
// 64 位输出请用 printf("%lld")

<think>根据用户描述,需要编写一个程序来解决多组测试数据下找出最长字符串的问题。 输入格式:第一行是一个正整数n(n<=10),表示字符串的个数。接下来n行,每行一个仅由英文字母组成的字符串,长度不超过50。 输出:应该输出最长的字符串。如果有多个字符串长度相同且都是最长,则输出第一个遇到的最长字符串(按照输入顺序,即先出现的那个)。 思路: 1. 读取第一行的整数n,表示字符串个数。 2. 循环n次,读取n个字符串,存储到一个列表中。 3. 遍历这个列表,找到最长的字符串(记录第一个最长的字符串)。 注意:题目要求输入多组测试数据,但根据描述,似乎每组测试数据都是以一个n开始,然后n行字符串。但是用户提到了“多组测试数据”,所以我们需要考虑处理多组测试数据的情况。然而,从输入描述来看,并没有明确说明多组测试数据的具体格式(比如是否以某个终止条件结束)。但常见的多组测试数据输入有两种方式: a) 第一行是测试数据组数t,然后每组数据第一行是n,接着n行字符串。 b) 多组测试数据,每组数据以n开始,当n=0时结束。 但是,用户的问题描述中只提到:“输入第一行为正整数n(n<=10)表示字符串个数”,并没有说有多组测试数据。然而,用户说“多组测试数据”,所以我们需要澄清。 再看用户提供的参考引用[1]中的代码,使用了: while True: try: ... except: break 这种方式可以处理多组测试数据直到输入结束(比如EOF)。 因此,我们可以这样设计: 程序持续读取输入,直到遇到文件结束符(EOF)为止。每组数据包括: 第一行:一个整数n(当n=0时,我们不处理,但题目没有说n=0结束,所以按照引用[1]的方式,我们可以一直读取直到输入结束) 接下来n行:每行一个字符串。 但是,用户的问题描述中并没有明确多组测试数据,只描述了一组数据。然而,用户提到了“多组测试数据”,并且参考了引用[1](该引用中处理了多组测试数据)。因此,我们按照多组测试数据来处理,每组数据以整数n开始,然后n行字符串。 步骤: 使用一个循环,不断读取测试组,直到遇到EOF(在标准输入中,通常是Ctrl+D或Ctrl+Z)或者读取失败(如空输入)。 对于每组测试数据: 读取n 如果n为0,可以跳过(但题目没有说n可能为0,所以我们可以不考虑,但为了保证健壮性,可以跳过该组) 读取n个字符串 在这n个字符串找出第一个最长的字符串并输出。 注意:题目要求输出最长的字符串,如果有多个字符串长度相同且最长,则输出第一个遇到的最长字符串(即输入顺序中最早出现的那个)。 实现方法: 我们可以遍历字符串列表,记录当前遇到的最大长度和对应的字符串。初始化最大长度为-1,最大字符串为None。 遍历每个字符串: 如果当前字符串的长度大于记录的最大长度,则更新最大长度和最大字符串。 这样,第一个遇到的最大长度字符串会被记录,后续遇到同样长度的不会更新(因为我们要求大于,而不是大于等于)。 或者,我们可以使用一个变量记录当前最大字符串,初始化为第一个字符串,然后从第二个字符串开始遍历,如果当前字符串长度大于记录的最大字符串长度,则更新。但是注意,这样第一个字符串就被初始化了,然后后面的字符串如果长度大于才更新,等于时不更新,这样就能保证保留第一个遇到的最长字符串。 但是,如果第一个字符串是空字符串,那么后续的非空字符串就会更新。所以这样是可行的。 具体代码(单组): n = int(input().strip()) max_str = "" # 初始化为空字符串,空字符串长度为0 for i in range(n): s = input().strip() if i == 0: max_str = s else: if len(s) > len(max_str): max_str = s 或者更简洁的,不区分i==0: max_str = "" # 初始为空,那么第一个字符串肯定比空字符串长,所以会更新 for i in range(n): s = input().strip() if len(s) > len(max_str): max_str = s 但是,注意:如果所有字符串都是空字符串,那么输出的就是空字符串,这符合要求。 但是,题目要求字符串由英文字母组成,所以可能不会出现空字符串?但输入可能包含空行吗?题目说“每行一个仅含英文字母”,所以应该不会出现空字符串(除非长度为0,但题目说长度不超过50,可以是0吗?)。题目没有明确说明,但按照描述“仅含英文字母”,那么空字符串(即长度为0)也是允许的,因为空字符串中没有非英文字母。 因此,我们按照上述方法。 但是,注意:题目要求多组测试数据,所以我们需要在一个循环中读取,直到EOF。 参考引用[1]的代码,我们使用try-except来捕获EOFError(当input()遇到EOF时,会抛出EOFError,但实际上是抛出一个EOF的异常,在Python中,EOFError是其中一个,但input()实际上在遇到EOF时抛出的是EOFError,但更通用的是用try-except捕获所有异常?引用[1]用了except: break,即捕获任何异常就退出。但在实际在线评测系统中,通常以EOF作为结束,所以这样写是常见的。 因此,整体代码结构: while True: try: n = int(input().strip()) max_str = "" for i in range(n): s = input().strip() if len(s) > len(max_str): max_str = s # 输出这组的最长字符串 print(max_str) except: break 但是,这样处理多组测试数据:每组数据输出一个最长字符串。 但是,用户的问题描述中并没有提到多组测试数据,而是说“输入第一行为正整数n”,然后n行。所以如果用户只输入一组数据,那么程序处理一组就结束了?但是,如果用户输入多组,那么就会连续处理。 根据用户提供的引用[1](HJ20密码验证合格程序)和引用[3]等,都是处理多组测试数据的,所以我们也按照多组测试数据来处理。 然而,我们还需要注意:题目要求输入的是“仅含英文字母”,但用户输入可能包含空格?题目说“每行一个”,所以每行就是一个字符串,使用input().strip()可以去掉行末的换行符和两端的空白。但是,题目要求仅含英文字母,所以两端的空格应该被去掉?但题目没有说字符串两端会有空格,所以使用strip()可能是不必要的,因为输入可能包含空格(如果题目允许字符串中有空格,但题目描述是“仅含英文字母”,所以字符串中不应该有空格?)。因此,我们不应该用strip()去掉空格,因为字符串中如果有空格,那么题目要求的是仅含英文字母,所以输入应该不会包含空格。但为了安全,题目要求的是每行一个字符串,所以每行就是一个字符串,我们直接读取整行,然后去掉末尾的换行符即可,但是两端的空格?题目没有说,所以按照题目的输入描述,字符串仅含英文字母,所以不会有前后空格。但是,为了安全,我们可以用strip(),因为如果输入有前后空格,那么strip()可以去掉,但这样会改变字符串内容(比如字符串本身有前后空格,但题目不允许空格,所以输入不会有空格,所以用strip()不会改变字符串)。或者,我们使用input().rstrip('\n')来只去掉换行符,保留空格。但是,题目描述没有提到空格,所以我们用strip()更安全,因为用户可能误输入空格。 但是,题目要求“仅含英文字母”,所以如果输入有空格,那么就是非法输入?我们不需要处理非法输入,所以可以直接读取整行然后strip(),这样保证字符串没有前后空格,如果字符串中间有空格,那么题目不允许,但题目没有说,所以假设输入不会包含空格。 因此,我们使用s = input().strip() 另外,注意:如果n=0,那么循环0次,max_str将保持为空字符串,然后输出空字符串。这符合逻辑,因为0个字符串中最长的字符串是空字符串(尽管不存在,但我们可以这样定义)。 但是,题目要求n<=10,且n为正整数,所以n>=1?用户说“正整数n”,所以n>=1。所以我们可以假设n>=1,这样就不需要处理n=0的情况。 因此,代码可以简化为: while True: try: n = int(input().strip()) max_str = "" # 初始为空,长度0 for i in range(n): s = input().strip() if len(s) > len(max_str): max_str = s print(max_str) except: break 但是,如果有多组数据,每组数据输出一个最长字符串,那么每组数据之间是独立的。 但是,用户的问题描述中并没有明确要求多组,所以我们需要根据用户提供的参考引用[1]来处理多组。 另外,用户提供的引用[1]的代码中,对每组数据进行了排序并输出所有字符串(排序后)。而我们的程序只需要输出最长的字符串(一个)。 因此,我们按照上述代码。 但是,我们考虑另一种情况:如果最长字符串有多个,我们只输出第一个遇到的。上述代码中,我们只在当前字符串长度大于max_str长度时才更新,所以如果后面遇到同样长度的,我们不会更新,因此保留的是第一个最长的字符串。这符合要求。 所以,最终代码: while True: try: n = int(input()) # 初始化最大字符串为空 max_str = "" for i in range(n): s = input().strip() # 如果当前字符串长度大于最大字符串的长度,则更新 if len(s) > len(max_str): max_str = s print(max_str) except: break 注意:在Python中,如果输入结束,input()会抛出EOFError,我们捕获所有异常(这里用except: break)来退出循环。 但是,我们也可以明确指定捕获EOFError和ValueError(当int(input())无法转换时),但题目保证了n是正整数,所以一般不会出错。但为了健壮性,我们可以只捕获EOFError,因为输入结束是我们退出的唯一条件。但是,如果输入n的时候输入了非数字,那么int()会抛出ValueError,这时程序会break退出。题目要求n是正整数,所以输入非数字的情况我们不考虑,直接退出程序。 因此,我们可以写: while True: try: n = int(input()) except EOFError: break except: # 如果输入的不是数字,我们也可以退出,或者跳过?但题目要求正整数,所以遇到非数字输入,我们视为结束? break 但为了简单,我们使用一个except: break,因为在线评测系统通常以EOF结束,而且输入都是合法的。 所以,我们使用第一个版本。 测试: 输入: 3 apple banana orange 输出:banana(因为banana和orange都是6个字符,但apple是5,banana是6,第一个遇到的最长字符串是banana?注意:我们是在读取过程中比较的,所以当读取到banana时,它比apple长,所以更新为banana,然后读取orange,长度等于banana,但是不大于,所以不更新。所以输出banana。 但是,如果输入: 3 orange banana apple 那么,第一个字符串orange长度6,然后banana长度6(不大于,所以不更新),apple长度5,所以输出orange(第一个最长的)。 符合要求。 因此,代码可以这样写。 但是,我们也可以将所有字符串读入列表,然后遍历列表找第一个最长的。这样也可以,而且更清晰。但是,我们可以在读取过程中就判断,这样不需要存储所有字符串(节省空间),但题目n<=10,所以存储也没有问题。 另一种方法: while True: try: n = int(input()) arr = [input().strip() for _ in range(n)] max_len = 0 ans = "" for s in arr: if len(s) > max_len: max_len = len(s) ans = s print(ans) except: break 两种方法都可以。 我们选择第二种,因为更清晰,并且存储空间要求不高。 所以,最终代码: while True: try: n = int(input().strip()) # 读取n个字符串 strings = [] for i in range(n): strings.append(input().strip()) # 初始化 max_str = strings[0] # 第一个字符串 for s in strings[1:]: if len(s) > len(max_str): max_str = s print(max_str) except: break 但是,注意:如果n=0,那么strings[0]会越界。但题目说n是正整数,所以n>=1,所以不会出现n=0。所以安全。 或者,我们可以使用: max_str = "" for s in strings: if len(s) > len(max_str): max_str = s 这样即使n=0,也不会进入循环,然后输出空字符串。但题目要求n>=1,所以我们不用担心。 我们采用第二种方法,使用列表。 现在,根据用户要求,生成相关问题。 注意:用户要求生成相关问题,我们可以在最后添加相关问题。 相关问题可以围绕这个程序展开,例如: 1. 如果要求输出所有最长的字符串(如果有多个)怎么办? 2. 如果要求输出最长字符串的长度而不是字符串本身怎么办? 3. 如果要求按字典序输出最长字符串(当有多个时)怎么办? 4. 如果输入数据量很大(虽然本题n<=10,但假设n很大),如何优化? 但是,由于本题非常简单,问题可以设计为: §§相关问题§§ 1. 如果要求输出所有最长字符串(当有多个最长字符串时)该如何修改程序? 2. 如果要求输出最长字符串的长度,程序应如何修改? 3. 如果要求按照字典序输出最长的字符串(当有多个最长字符串时,输出字典序最小的),程序应如何修改? 因此,我们输出代码和问题。 </think> ### 解决最长字符串查找问题 根据需求,需要编写一个程序处理多组测试数据,每组数据包含一个正整数 $n$ 和 $n$ 个字符串,输出其中**长度最长且输入顺序最先出现**的字符串。以下是完整实现: ```python while True: try: # 读取字符串个数 n = int(input().strip()) max_str = "" # 初始化最长字符串 # 遍历所有输入字符串 for _ in range(n): s = input().strip() # 遇到更长的字符串时更新(相等时不更新,保证保留第一个最长串) if len(s) > len(max_str): max_str = s print(max_str) # 输出结果 except: break # 捕获EOF或异常时退出 ``` #### 代码说明: 1. **多组数据处理**: 使用 `while True` 循环持续读取输入,通过 `try-except` 捕获 `EOFError`(输入结束)或其他异常,确保兼容多组测试数据[^1]。 2. **核心逻辑**: - 初始化 `max_str` 为空字符串(长度0) - 每读入一个字符串,比较其长度与 `max_str` 的长度 - **仅当新字符串更长时更新**(保证相等时保留最早出现的字符串) 3. **输入要求**: - $n \leq 10$,字符串仅含英文字母,长度 $\leq 50$ - 示例输入: ``` 3 apple banana orange ``` - 输出:`banana`(最早出现的最长字符串) #### 示例执行: | 输入 | 输出 | |------|------| | `2`<br>`hello`<br>`world` | `hello`(长度相同,取第一个) | | `3`<br>`cat`<br>`elephant`<br>`dog` | `elephant`(长度最长) | #### 注意事项: - 使用 `strip()` 确保去除字符串两端空白符 - 时间复杂度:$O(n)$,空间复杂度:$O(1)$(仅存储一个最长字符串
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值