【剑指offer】66.第一个只出现一次的字符
总目录:
1.问题描述
在一个长为 字符串中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
数据范围:0≤n≤10000,且字符串只有字母组成。
要求:空间复杂度 O(n),时间复杂度 O(n)
2.问题分析
1哈希
看到查找出现次数的就应想到哈希表,因为其时间复杂度O(1)的特性,
需要两次遍历,第1次是填充哈希表,第2次是查询出现次数
2队列+哈希表
题中要求“第一个只出现一次的字符”,意味着该字符前面的字符(如果有的话)是重复的、需要被忽略掉,这种前面的需要被抛弃掉的特性可以想到队列。
对于这些元素,在遍历到输入集合结尾时必然已经遇到,问题是如何将这些元素剔除。
使用一个哈希表来保存元素是否出现过、使用一个队列来保证元素出现的顺序。
遍历元素时如果是新元素,则将其加入到哈希表中、并在队列中入队;
如果是已经遇到过的元素,则触发对队列中front元素的重复性检查、如果重复则出队、while循环此操作直到front元素尚未重复。
这样使用循环嵌套使得表面上看起来只对输入集合遍历了一次。,当遍历完成后,front元素即只出现了一次的元素,问题是它的地址是多少?
只需要队列中储存的是pair<val,addr>即可。
3.代码实例
哈希
1 class Solution { 2 public: 3 int FirstNotRepeatingChar(string str) { 4 unordered_map<char, int> maps; 5 for (char a : str) { 6 maps[a]++; 7 } 8 9 for (int i = 0; i < str.length(); i++) { 10 if (maps[str[i]] == 1) { 11 return i; 12 } 13 } 14 15 return -1; 16 } 17 };
队列+哈希
1 class Solution { 2 public: 3 int FirstNotRepeatingChar(string str) { 4 //统计字符出现的位置 5 unordered_map<char, int> mp; 6 queue<pair<char, int> > q; 7 for(int i = 0; i < str.length(); i++){ 8 //没有出现过的字符 9 if(!mp.count(str[i])){ 10 mp[str[i]] = i; 11 q.push(make_pair(str[i], i)); 12 //找到重复的字符 13 }else{ 14 //位置置为-1 15 mp[str[i]] = -1; 16 //弹出前面所有的重复过的字符 17 while(!q.empty() && mp[q.front().first] == -1) 18 q.pop(); 19 } 20 } 21 return q.empty() ? -1 : q.front().second; 22 } 23 };
需要注意的是:
第二种方法速度有提升但也不能说只需要遍历一次,只是因为循环的嵌套使得最外层的循环看起来只遍历了1次。 在时间复杂度上最坏的情况是唯一出现一次的值在正中间、且输入序列中第0个和最后一个重合,这就使得在遍历到最后一个元素时需要出队n/2次才能找到目标值。 方法1时间复杂度是O(2n),方法2时间复杂度是O(n+n/2)
本文作者:啊原来是这样呀
本文链接:https://www.cnblogs.com/OhOfCourse/p/16953200.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步