题目描述:
在一个长为 字符串中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -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{ // 位置置为-1 mp[str[i]] = -1; // 弹出前面所有的重复过的字符 while(!q.empty() && mp[q.front().first] == -1) q.pop(); } } return q.empty() ? -1 : q.front().second; } };