题目
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
案例:
s = "leetcode" 返回 0. s = "loveleetcode", 返回 2.
注意事项:您可以假定该字符串只包含小写字母。
我的思路:
1、用一个map来存储每个字符出现的次数
2、将出现次数超过一次的放进一个set里
3、将set元素遍历与string的每个元素做对比,第一次出现相同的即可直接返回该元素在charArray内的坐标,
4、需要注意:当所有字母都重复的时候,此时set集合的长度为0,返回-1;完成该题。
class Solution {
public int firstUniqChar(String s) {
HashMap<Character,Integer> map = new HashMap<Character,Integer>();
char[] schar = s.toCharArray();
for (int i = 0; i < schar.length; i ++){
if (map.get(schar[i]) == null){
map.put(schar[i],1);
}else {
map.put(schar[i],map.get(schar[i])+1);
}
}
Set<Character> set = new HashSet<>();
for (Map.Entry<Character,Integer> entry : map.entrySet()){
if (entry.getValue() == 1){
set.add(entry.getKey());
}
}
int res = 0;
for (int i = 0; i < schar.length; i ++){
for (Character set1 : set){
if (schar[i] == set1){
return res = i;
}
}
}
if (set.size() == 0) return -1;
return res;
}
}
不足之处:申请了太多的额外空间,而且算法效率对于这道题来说应该是比较慢的。
借鉴一下他人的方法
方法一:
1、遍历字符串,对每个元素取其最早出现位置
2、根据该位置查找该字符的首次出现的index和最后出现的一次index是否相同,相同即返回该字符的位置,不相同则继续查找下一个,如果一致找不到则返回-1;
class Solution {
public int firstUniqChar(String s) {
char a = ' ';
for(int i=0; i<s.length(); ++i) {
a = s.charAt(i);
if(s.indexOf(a) == s.lastIndexOf(a)) {
return i;
}
}
return -1;
}
}
这个方法思路清晰。
还有更快的
public class FirstUniqCharOthersQuickerEdition {
public int firstUniqChar(String s) {
int res = -1;
for(char ch='a'; ch<='z'; ch++) {
int index = s.indexOf(ch);
System.out.println("index: "+index);
if(index != -1 && index == s.lastIndexOf(ch)) {
System.out.println("res(before): "+res);
res = res == -1?index:Math.min(res, index);
System.out.println("res(after): "+res);
}
}
return res;
}
public static void main(String[] args) {
FirstUniqCharOthersQuickerEdition firstUniqCharOthersQuickerEdition = new FirstUniqCharOthersQuickerEdition();
System.out.println(firstUniqCharOthersQuickerEdition.firstUniqChar("bbcddefg"));
}
}
一开始有些看不明白,于是我修改了一下,弄几个print看看细节的执行流程
index: -1
index: 0
index: 2
res(before): -1
res(after): 2
index: 3
index: 5
res(before): 2
res(after): 2
index: 6
res(before): 2
res(after): 2
index: 7
res(before): 2
res(after): 2
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
index: -1
2
Process finished with exit code 0
哦,大致明白了。
思路就是:
1、用二十六个字母遍历,如果字符串里面出现了该字母,并且该字母在字符串内的第一次出现的索引和最后一次出现的索引一致,则进入res的赋值。
2、因为是根据abc-xyz的顺序来遍历的,所以res需要实时更新,不然就按照顺序赋值了,不按字母顺序执行的时候,就取Math.min(res,index),这个是为了找到第一个出现的不重复的值索引所设计的。