作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处
题目描述:
在一个长为 字符串中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
数据范围:0≤n≤10000,且字符串只有字母组成。
要求:空间复杂度O(n),时间复杂度O(n)
示例:
输入:
"google"
返回值:
4
解题思路:
本题考察算法思维。两种解题思路:
1)哈希法
- 第一次循环用哈希表记录所有字符出现次数。
- 第二次循环找到首个出现次数为1的字符即可。
2)位运算
- 本质上和哈希法一样。因为字符只有字母,数量为26*2=52。每一位表示一个字符,比如字符b就是0010。
- 第一次循环用b记录出现过的字符,相应位数设为1,如果出现过了则flag对应位数也设为1。
- 第二次循环如果某个字符在b中对应位数为1,在flag中为0,则说明只出现过一次,完毕。
3)队列哈希法
- 该方法执行一次循环即可。
- 当字符首次出现,哈希表存储该字符位置,并将其放入队列中。
- 如果出现重复字符,则哈希表将该字符位置信息设为-1,即无效,并依次弹出队列中位置为-1的数据。注意,如果重复字符并非首个字符,则不进行弹出操作。如abcb,则不弹;如abcba,则将队列abc中的ab弹出,只剩下的c也就是答案。
测试代码:
1)哈希法
class Solution {
public:// 首个不重复字符int FirstNotRepeatingChar(string str) {int size = int(str.size());unordered_map<char, int> mp;// 统计每个字符出现的次数for(int i = 0; i < size; i++){mp[str[i]]++;} // 找到第一个只出现一次的字母for(int i = 0; i < size; i++){if(mp[str[i]] == 1)return i;} // 没有找到return -1;}
};
2)位运算
class Solution {
public:// 首个不重复字符int FirstNotRepeatingChar(string str) {int size = int(str.size());long long b = 0;long long flag = 0;// 统计每个字符出现的次数for(int i = 0; i < size; i++){int temp = str[i] - 'a';if(b & (1 << temp)){flag |= (1 << temp);}b |= (1 << temp);} // 找到第一个只出现一次的字母for(int i = 0; i < size; i++){int temp = str[i] - 'a';if((b & (1 << temp)) && !(flag & (1 << temp))){return i;}} //没有找到return -1;}
};
3)队列哈希法
class Solution {
public:// 首个不重复字符int FirstNotRepeatingChar(string str) {int size = int(str.size());unordered_map<char, int> mp;queue<pair<char, int> > q;// 统计字符出现的位置for(int i = 0; i < size; i++){// 没有出现过的字符if(!mp.count(str[i])){mp[str[i]] = i;q.push(make_pair(str[i], i));// 找到重复的字符}else{// 位置置为-1mp[str[i]] = -1;// 弹出前面所有的重复过的字符while(!q.empty() && mp[q.front().first] == -1)q.pop();}}return q.empty() ? -1 : q.front().second;}
};