找一个字符串中第一个只出现一次的字符(牛客网)

本文介绍了如何高效地找到字符串中第一个只出现一次的字符。通过利用哈希表记录每个字符的出现次数,可以在遍历过程中以O(1)的时间复杂度找到目标字符,从而优化算法性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

思路:普通思路就是先看第一个元素,遍历字符串看看每个字符总共在字符串中出现的次数,但是这是一个时间复杂度O(N)的算法,牛客上面是肯定跑不过的,所以我们可以想到用什么东西可以达到记录字符出现次数时间复杂度有符合要求的呢?

哈希表
这里是一个字符串,每个字符的取值范围不可能超过256,我们可以直接将哈希表定义出来并且初始化为全0,然后对应字符的ASCII存放在字符串中出现的次数,后面就可以遍历哈希表来确定哪一个字符是字符串中只出现一次的,由于我们是根据str[i]来遍历就可以保证遍历的时候就是按照原字符串中字符出现的先后顺序来的,一旦遇到hashtable[str[i]]==1,就直接返回

#include<iostream>
using namespace std;
#include<string>
#include<assert.h>
char FindFirst(string str){
    assert(str.size() > 0);
    int hashtable[256] = { 0 };
    int i = 0;
    for ( i = 0; i < str.size(); i++){
        hashtable[str[i]]++;
    }
    for (i = 0; i< str.size(); i++){
        if (hashtable[str[i]] == 1){
            return str[i];
        }
    }
    return 0;
}
int main(){
    string str = "qabcdfabcde";
    char ret = FindFirst(str);
    cout << ret << endl;
    system("pause");
    return 0;
}
<think>嗯,用户想知道在C++中如何简单实现字符串第一个只出现一次字符。我记得这个问题通常在面试题里出现,比如牛客网可能有类似的题目。首先,我需要回忆一下常见的解决方法。 可能的思路是用哈希表或者数组来统计每个字符出现的次数。因为ASCII字符共有128个,所以可以用一个大小为128的数组来记录次数,这样可能更高效。然后,再次遍历字符串第一个计数为1的字符。 那具体步骤应该是这样的:首先,遍历字符串,统计每个字符的出现次数。然后,再遍历一遍字符串,检查每个字符对应的数组值是否为1,第一个符合条件的字符就是答案。如果都没有,可能返回空或者某个特定值。 需要考虑的是字符的范围,比如是否是扩展ASCII或者其他编码,但题目里提到ASCII的话,128应该足够。然后要注意字符串为空的情况,需要处理边界条件。 代码方面,应该先声明一个大小为128的数组,初始化为0。然后,第一次循环统计次数。第二次循环逐个字符检查,第一个次数为1的。例如,字符串"abaccdeff",遍历统计后,b、d、e、f的计数是1。然后第二次遍历时,第一个出现的是b,所以返回b。 可能还需要注意字符的处理,比如是否区分大小写,但题目里没特别说明,应该假设都是小写或者按原样处理。此外,如果字符串中没有符合条件的字符,应该返回什么?比如返回空字符或者-1,这需要根据题目要求决定。 然后,代码实现的话,函数可以接收一个字符串参数,返回char类型。例如: char firstUniqChar(string s) { int count[128] = {0}; for(char c : s) { count[c]++; } for(char c : s) { if(count[c] == 1) { return c; } } return '\0'; } 这样应该可以了。测试一下例子,比如输入"abaccdeff",返回'b'。如果是空字符串或者全重复的,返回空字符。 用户可能需要更简单的实现,比如不使用STL的unordered_map,而用数组更高效。所以这个方法应该满足要求,时间复杂度O(n),空间复杂度O(1)因为数组大小固定。 可能的问题比如:为什么用数组而不是哈希表?因为数组更高效,直接通过ASCII码访问,而哈希表需要处理哈希冲突,虽然对于字符来说可能影响不大,但数组更简单快捷。 总结下来,这个方法是可行的,且符合题目要求的简单实现。需要检查代码是否有语法错误,比如C++中的范围循环是否正确,数组初始化是否正确。例如,int count[128] = {0};会将所有元素初始化为0,这在C++中是允许的。然后返回'\0'表示没有到。 用户可能还想知道其他方法,比如使用find和rfind函数,逐个检查每个字符第一个和最后一个出现位置是否相同,但这种方法的时间复杂度是O(n^2),对于长字符串效率不高,所以统计次数的方法更优。 所以,最终的答案应该给出这个数组统计的方法,并解释步骤,同时考虑可能的边界情况。</think>### C++查第一个仅出现一次字符实现步骤 1. **创建字符计数数组** 使用ASCII码值索引的整型数组统计字符出现次数,数组大小固定为128(标准ASCII字符总数)。初始化时自动填充零值: ```cpp int count[128] = {0}; ``` 2. **首次遍历统计频率** 遍历字符串的每个字符,对应ASCII索引的计数加一: ```cpp for (char c : str) { count[static_cast<int>(c)]++; } ``` 3. **二次遍历定位目标** 再次遍历字符串第一个计数为1的字符: ```cpp for (char c : str) { if (count[static_cast<int>(c)] == 1) { return c; // 立即返回第一个符合条件的字符 } } return '\0'; // 无符合条件时返回空字符 ``` ### 完整代码实现 ```cpp #include <iostream> using namespace std; char firstUniqChar(const string& s) { int count[128] = {0}; // ASCII字符统计数组[^1] for (char c : s) { count[c]++; } for (char c : s) { if (count[c] == 1) { return c; } } return '\0'; } int main() { string test = "abaccdeff"; cout << "第一个唯一字符: " << firstUniqChar(test); // 输出 b return 0; } ``` ### 算法特性 - **时间复杂度**: $O(n)$,两次线性遍历 - **空间复杂度**: $O(1)$,固定长度数组 - **边界处理**: 空字符串返回`\0`,全重复字符返回`\0`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值