CS-Notes/notes/50. 第一个只出现一次的字符位置.md
2020-11-04 01:28:12 +08:00

61 lines
2.0 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 50. 第一个只出现一次的字符位置
## 题目链接
[牛客网](https://www.nowcoder.com/practice/1c82e8cf713b4bbeb2a5b31cf5b0417c?tpId=13&tqId=11187&tPage=1&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking&from=cyc_github)
## 题目描述
在一个字符串中找到第一个只出现一次的字符并返回它的位置字符串只包含 ASCII 码字符
```
Input: abacc
Output: b
```
## 解题思路
最直观的解法是使用 HashMap 对出现次数进行统计字符做为 key出现次数作为 value遍历字符串每次都将 key 对应的 value 1最后再遍历这个 HashMap 就可以找出出现次数为 1 的字符
考虑到要统计的字符范围有限也可以使用整型数组代替 HashMapASCII 码只有 128 个字符因此可以使用长度为 128 的整型数组来存储每个字符出现的次数
```java
public int FirstNotRepeatingChar(String str) {
int[] cnts = new int[128];
for (int i = 0; i < str.length(); i++)
cnts[str.charAt(i)]++;
for (int i = 0; i < str.length(); i++)
if (cnts[str.charAt(i)] == 1)
return i;
return -1;
}
```
以上实现的空间复杂度还不是最优的考虑到只需要找到只出现一次的字符那么需要统计的次数信息只有 0,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;
}
```
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-2.png"></img></div>