题目:给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
示例:
s = "leetcode"
返回 0
s = "loveleetcode"
返回 2
提示:你可以假定该字符串只包含小写字母。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-unique-character-in-a-string
题解一:1、根据给定的字符串,转化为数组存储字符出现的个数;2、重新遍历字符串,首次出现字符在个数数组中值为1,则返回改字符的索引。
1 public int firstUniqChar(String s) {
2 // Map<Character,Integer> frequency = new HashMap();
3 // for(int i=0;i<s.length();i++){
4 // char ch = s.charAt(i);
5 // frequency.add(ch,frequency.getOrDefault(ch,0)+1);
6 // }
7 // for(int i=0;i<s.length();i++){
8 // if(frequency.get(s.charAt(i))==1){
9 // return i;
10 // }
11 // }
12 // return -1;
13
14 int[] count = new int[26];
15 for(int i=0;i<s.length();i++){
16 char ch = s.charAt(i);
17 count[ch-'a']++;
18 }
19
20 for(int i=0;i<s.length();i++){
21 if(count[s.charAt(i)-'a']==1){
22 return i;
23 }
24 }
25 return -1;
26 }
题解二:1、类似题解一,用Map来存储字符和出现次数;2、遍历字符串,根据字符去Map中找次数,首次找到值为1的字符,返回其索引。
1 public int firstUniqChar(String s) {
2 Map<Character,Integer> frequency = new HashMap();
3 for(int i=0;i<s.length();i++){
4 char ch = s.charAt(i);
5 frequency.put(ch,frequency.getOrDefault(ch,0)+1);
6 }
7 for(int i=0;i<s.length();i++){
8 if(frequency.get(s.charAt(i))==1){
9 return i;
10 }
11 }
12 return -1;
13
14
15 }
题解三:1、改用Map存储字符和对应的索引(第一次出现才保存索引,否则保存-1);2、遍历Map中的键值对Entry,直到找到索引不为-1且索引值最小的,返回索引。
1 public int firstUniqChar(String s) {
2 //用hash表存储索引
3 //判断值,如果值是第一次出现,则保存索引;如果是多次出现,则将索引修改为-1
4 Map<Character,Integer> position = new HashMap();
5 int n = s.length();
6 for(int i=0;i<n;i++){
7 char ch = s.charAt(i);
8 if(position.containsKey(ch)){
9 position.put(ch,-1);
10 }else{
11 position.put(ch,i);
12 }
13 }
14 int first = n;
15 for(Map.Entry<Character,Integer> entry:position.entrySet()){
16 int pos = entry.getValue();
17 if(pos!=-1 && pos < first){
18 first = pos;
19 }
20 }
21 if(first == n){
22 return -1;
23 }
24 return first;
25
26
27
28 }
题解四:1、Map+队列融合使用,首先判断Map中是否存在字符,如果没有,使用Map保存字符和索引,同时加入队列中;如果存在,则进一步判断队首;2、借助队列先进先出的特性,只要将重复值和对首比较,队首值重复则出队。;2、如果队不为空,则取出队首对应的索引
1 class Solution {
2 public int firstUniqChar(String s) {
3 //借助队列找到一个不重复的字符。队列具有【先进先出】的性质,因此很适合用来找出第一个满足某个条件的元素
4 //具体地,我们使用与方法二相同的哈希映射,并且使用一个额外的队列,按照顺序存储每一个字符以及他们第一次出现的位置。
5 //当我们对字符串进行遍历时,设当前遍历到的字符为c,如果c不在哈希映射中,我们就将c与它的索引作为一个二元组放入队尾,否则我们就需要检查队列
6 //中的元素是否都满足【只出现一次】的要求,即我们不断地根据哈希映射中存储的值(是否为1)选择弹出队首的元素,知道队首元素【真的】只出现了一
7 //次或者队列为空。
8
9 //在遍历完成后,如果队列为空,说明没有不重复的字符,返回为-1,否则队首的元素即为第一个不重复的字符以及其索引的二元组。
10
11 Map<Character,Integer> position = new HashMap();
12 int n = s.length();
13 Queue<Pair> queue = new LinkedList<Pair>();
14 for(int i=0;i<n;i++){
15 char ch = s.charAt(i);
16 if(!position.containsKey(ch)){
17 position.put(ch,i);
18 queue.offer(new Pair(ch,i));
19 }else{
20 position.put(ch,-1);
21 //当队列不为空,且当前队列中队首的取出元素在hash中对应的索引,如果是-1,则删除队首
22 while(!queue.isEmpty() && position.get(queue.peek().ch) == -1){
23 queue.poll();
24 }
25 }
26 }
27 //对比完所有字符之后,取出队首元素,队为空,则返回-1
28 return queue.isEmpty() ? -1:queue.peek().pos;
29
30 }
31
32 class Pair{
33 char ch;
34 int pos;
35
36 Pair(char ch,int pos){
37 this.ch = ch;
38 this.pos = pos;
39 }
40 }
41 }