![cebd4e5dc17ca4670647927eaa36cf2d.png](https://i-blog.csdnimg.cn/blog_migrate/b454f70fd60f20061736dd01ccb71afd.jpeg)
题目描述
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
解题思路及代码
方法一:哈希法
遍历一遍字符串,统计每个字符出现的次数。然后再遍历一遍字符串,找到第一个只出现一次的字符。
使用 map 实现:
class Solution {
public:
int FirstNotRepeatingChar(string str) {
unordered_map<char, int> mp;
for (const char ch : str) {
++mp[ch];
}
for (int i=0; i<str.length(); ++i) {
if (mp[str[i]] == 1) return i;
}
return -1;
}
};
使用数组代替 map:
class Solution {
public:
int FirstNotRepeatingChar(string str) {
int mp[128] = {0};
for (const char ch : str) {
++mp[ch];
}
for (int i=0; i<str.length(); ++i) {
if (mp[str[i]] == 1) return i;
}
return -1;
}
};
时间复杂度:O(2n), 需要遍历两次字符串
空间复杂度:O(n)
方法二:使用 bitset
本质上还是哈希法,只是使用 bitset 更节省空间。
具体过程:
- 初始化:bitset<128> b1表示只出现1次, b2表示出现2次以上
- 遍历字符串,第一次出现,b1[ch] = 1
- 如果第二次出现,b2[ch] = 1
- 最后,找出第一个b1[ch] == 1 && b2[ch] == 0的字符
代码:
class Solution {
public:
int FirstNotRepeatingChar(string str) {
bitset<128> b1, b2;
for (const char ch : str) {
if (!b1[ch] && !b2[ch]) {
b1[ch] = 1;
}
else if (b1[ch] && !b2[ch]) {
b2[ch] = 1;
}
}
for (int i=0; i<str.length(); ++i) {
if (b1[str[i]] && !b2[str[i]]) {
return i;
}
}
return -1;
}
};
Java 版:
public int FirstNotRepeatingChar2(String str) {
BitSet bs1 = new BitSet(128);
BitSet bs2 = new BitSet(128);
for (char c : str.toCharArray()) {
if (!bs1.get(c) && !bs2.get(c))
bs1.set(c); // 0 0 -> 0 1
else if (bs1.get(c) && !bs2.get(c))
bs2.set(c); // 0 1 -> 1 1
}
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (bs1.get(c) && !bs2.get(c)) // 0 1
return i;
}
return -1;
}
时间复杂度:O(2n), 需要遍历两次字符串
空间复杂度:O(n)
解析参考来自:
第一个只出现一次的字符_牛客网www.nowcoder.com