文章目录
前言
用几种方式都做错了
一、字符串中的第一个唯一字符
题目:给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 ;
摘要:字符串、找到第一个、不重复的字符、返回不重复字符的索引、如果没找到则返回-1;
原思想:
刚开始想用数组,然后进行数组排序,创建集合,把元素添加到集合中,返回能添加元素的第一个元素,后来发现,不管怎样,都会添加一个元素进去,无法区分重复与否;
然后就说用双指针,队数组进行两次循环,当遍历指向前指针指向元素和后指针指向元素相等时则跳出内层循环,如果不相等,则让后指针指向元素的下标等于一个变量k,这里也出错了,有两个问题,第一个问题是数组排序后,打乱了原有字符串的相对位置,第二个问题是,如果是aabcb这种情况会返回b的下标;
原代码:
class Solution {
public int firstUniqChar(String s) {
String[] chars = s.split("");
int i=0;
int k=0;
for(int j=0;j<chars.length;j++){
for(int l=1;l<chars.length;l++){
if(chars[j]==chars[l]){
break;
}
else{
k=j;
}
}
if(chars[j])
}
return k;
}
}
问题:
问题在原想法中
新思想:
1.两次遍历:
第一遍先统计每个字符出现的次数,第二遍再次从前往后遍历字符串s中的每个字符,如果某个字符出现一次直接返回;
2.使用HashMap解决:
这里利用HashMap的key-value的特性,保存每个字符串出现的次数,第一个出现为一次的就是要返回的;
3.使用java的api:
一个从后往前找,一个从前往后找,如果是同一元素的下标位置都一样,那么就说明它只出现了一次;
对于思想1的新代码:
public int firstUniqChar(String s) {
int count[] = new int[26];
char[] chars = s.toCharArray();
//先统计每个字符出现的次数
for (int i = 0; i < s.length(); i++)
count[chars[i] - 'a']++;//a~z单词出现的次数,count[0]=1,代表a出现1次
//有26个小写字母,定义了一个length为26的数组,下标0-25,
//每个字母对应一个,根据ASCII值计算,
//a~z对应97~122,a则为a-a即为0,z则为z-a即为25,a-z之间的也一一对应。
for (int i = 0; i < s.length(); i++)
if (count[chars[i] - 'a'] == 1)
return i;
return -1;
}
对于思想2的新代码:
public int firstUniqChar(String s) {
Map<Character, Integer> map = new HashMap();
char[] chars = s.toCharArray();
//先统计每个字符的数量
for (char ch : chars) {
map.put(ch, map.getOrDefault(ch, 0) + 1);
//getOrDefault是按字符ch的出现次数增加,如果一次都没有,则默认从零开始加一
}
//然后在遍历字符串s中的字符,如果出现次数是1就直接返回
for (int i = 0; i < s.length(); i++) {
if (map.get(chars[i]) == 1) {
return i;
}
}
return -1;
}
对于思想3的新代码:
public int firstUniqChar(String s) {
for (int i = 0; i < s.length(); i++)
if (s.indexOf(s.charAt(i)) == s.lastIndexOf(s.charAt(i)))
return i;
return -1;
}
总结
1.字符串转数组的方法:
s是一个字符串;
s.toCharArray();//将字符串转成字符数组O;
2.HsahMap统计次数,即可用到查早重复数据,又可以用到查非重复数据;
3.charAt(i)可以查找i位置的字符,indexOf(字符)查出来的是字符的下标;