1. 题目
2. 思路
(1) 哈希表
- 创建一个内部类CharInfo,用于存储字符首次出现时的下标和是否只出现过一次的状态。
- 首先遍历字符串,若哈希表中已经存在该字符,则将该字符只出现过一次的状态修改为false;若哈希表中不存在该字符,则将该字符及其CharInfo对象存入哈希表。
- 最后遍历哈希表,找出只出现过一次且下标最小的字符,返回即可。
(2) 队列
- 在(1)的基础上,舍弃了内部类,使用了队列。
- 首先遍历字符串,当字符第一次出现时,将其同时加入队列,利用队列先进先出的特性,维持字符第一次出现的顺序。
- 最后遍历队列,找出第一个只出现过一次的字符,返回即可。
(3) 有序哈希表
- 在(1)的基础上,改为使用LinkedHashMap类。
- 该类存储了键值对添加时的顺序,利用foreach循环遍历哈希表时,按照键值对添加时的顺序进行遍历。
(4) 数组
- 由于题目说明了只会出现26个小写字母,因此可以声明长度为26的int数组,用于存储每个字母出现的次数。
- 第一次遍历字符串存储每个字母出现的次数。
- 第二次遍历字符串找到第一个出现次数为1的字母,返回即可。
3. 代码
import java.util.*;
public class Test {
public static void main(String[] args) {
Solution2 solution = new Solution2();
System.out.println(solution.firstUniqChar("leetcode"));
}
}
class Solution {
private class CharInfo {
private int index;
private boolean unique;
public CharInfo(int index, boolean unique) {
this.index = index;
this.unique = unique;
}
}
public char firstUniqChar(String s) {
char result = ' ';
Map<Character, CharInfo> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
if (map.containsKey(s.charAt(i))) {
map.get(s.charAt(i)).unique = false;
} else {
map.put(s.charAt(i), new CharInfo(i, true));
}
}
int index = Integer.MAX_VALUE;
for (Map.Entry<Character, CharInfo> entry : map.entrySet()) {
if (entry.getValue().unique == true && entry.getValue().index < index) {
result = entry.getKey();
index = entry.getValue().index;
}
}
return result;
}
}
class Solution1 {
public char firstUniqChar(String s) {
Map<Character, Boolean> map = new HashMap<>();
Queue<Character> queue = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
if (map.containsKey(s.charAt(i))) {
map.put(s.charAt(i), false);
} else {
map.put(s.charAt(i), true);
queue.offer(s.charAt(i));
}
}
while (!queue.isEmpty()) {
char c = queue.poll();
if (map.get(c) == true) {
return c;
}
}
return ' ';
}
}
class Solution2 {
public char firstUniqChar(String s) {
Map<Character, Boolean> map = new LinkedHashMap<>();
for (int i = 0; i < s.length(); i++) {
if (map.containsKey(s.charAt(i))) {
map.put(s.charAt(i), false);
} else {
map.put(s.charAt(i), true);
}
}
for (Map.Entry<Character, Boolean> entry : map.entrySet()) {
if (entry.getValue() == true) {
return entry.getKey();
}
}
return ' ';
}
}
class Solution3 {
public char firstUniqChar(String s) {
int[] count = new int[26];
for (int i = 0; i < s.length(); i++) {
count[s.charAt(i) - 'a']++;
}
for (int i = 0; i < s.length(); i++) {
if (count[s.charAt(i) - 'a'] == 1) {
return s.charAt(i);
}
}
return ' ';
}
}