给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
示例:
s = "leetcode" 返回 0 s = "loveleetcode" 返回 2
提示:你可以假定该字符串只包含小写字母。
题目解析:
找到一个字符串中第一个不重复的字符,并将其下标地址返回。
解题思路一:
我们可以首先将字符串转换成字符列表,然后逐步遍历,利用Map统计每个字符的个数。最后在从头开始遍历字符,在Map中查找对应的值是否为1,如果为1,直接返回下标地址即可。如果没找到,则直接返回-1。
代码实现:
class Solution {
public int firstUniqChar(String s) {
Map<Character,Integer> map = new HashMap<>();
int len = s.length();
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
map.put(c,map.getOrDefault(c,0) + 1);
}
for (int i = 0; i < len; i++) {
if (map.get(s.charAt(i)) == 1){
return i;
}
}
return -1;
}
}
执行结果:
解题思路一变种:
上述查询比较慢,主要是匹配字符串的时候,全字符匹配,我们可以优化一下,将字符替换成ASII值,匹配速度会快一点。
代码实现:
class Solution {
public int firstUniqChar(String s) {
int[] buckets = new int[26];
int n = s.length();
for (int i = 0; i < n; i++) {
buckets[s.charAt(i) - 'a']++;
}
for (int i = 0; i < n; i++) {
if (buckets[s.charAt(i) - 'a'] == 1) {
return i;
}
}
return -1;
}
}
执行结果:
解题思路二:
由于字符串中只会存在小写字母,所以我们可以直接从a-z开始遍历,然后使用indexOf()和lastIndexOf()方法查找字符,如果两个方法返回的index相等,且不等于-1,且小于字符列表长度,则可直接返回该索引,否则返回-1。
代码实现:
class Solution {
public int firstUniqChar(String s) {
int ans = s.length();
for (int i = 0; i < 26; i++) {
char ch = (char) ('a' + i);
int index = s.indexOf(ch);
if ((index != -1) && (index == s.lastIndexOf(ch)) && (index < ans)) {
ans = s.indexOf(ch);
}
}
return ans == s.length() ? -1 : ans;
}
}
执行结果:
总结:
1. 遇到这种涉及到某个字符出现次数的问题时,我们可以首先想到用hash来解决问题,然后可以进行逐步优化。
2. 当匹配字符比较慢时,可以将其转换成其他的易匹配的值,这样也可以提高匹配效率。
3. 同时,我们也可以利用题目中给我们提供的特殊条件,进行特殊的处理,来提高程序的运行效率。
喜欢本文的话,可以关注一下公众号,每天定时更新一篇学习日记,让我们一起成长!