剑指offer_JZ34_第一个只出现一次的字符
问题描述
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
示例1
输入
“google”
返回值
4
思路1(借助HashMap)
因为他的字符串长度是有限的,而且我们需要找到只出现一次的字符,我们可以首先考虑用Hashmap这样的数据结构来把所有出现过的字符和他们对应的出现次数记录下来。接着,因为我们需要找到第一个只出现一次的字符,所以我们还需要把整个输入的字符串再遍历一遍,然后遍历时我们检测当前字符的出现次数在我们的hashmap里是不是1,如果我们一旦遇到符合条件的字符,直接返回他的位置,因为我们只要第一个符合条件的字符。所以这题分两步:
1.创建一个hashmap,然后遍历整个字符串一遍,记录下每个字符出现的次数(key表示当前字符,value表示当前字符出现的次数)
2.再次遍历整个字符串,根据我们前面存储的hashmap找哪个字符只出现过一次,直接返回他的位置
这里有个重点是,题目里说,字符需要区分大小写,因为我们这里是直接存储的字符,所以我们并没有改变他的大小写,所以不用进行额外的操作。但是如果题目产生变形,不需要区分大小写,我们可以在存储时把所有的字符都变成大写或者小写,放进hashmap的keyset里,然后找的时候也进行相应的变形,就可以了。
【注】:在hashmap底层,存储数据到entry数组时是按照key的哈希值计算的存储位置,而与字符数组遍历顺序无关。
import java.util.*;
public class Solution {
public int FirstNotRepeatingChar(String str) {
if(str.length() == 0 || str == null)
return -1;
Map<Character,Integer> map = new HashMap<Character,Integer>();
for(int i =0; i < str.length(); i++){
if(!map.keySet().contains(str.charAt(i))){
map.put(str.charAt(i), 1);
}else{
map.put(str.charAt(i), map.get(str.charAt(i)) + 1);
}
}
for(int i=0; i<str.length(); i++){
if(map.get(str.charAt(i)) == 1)
return i;
}
return -1;
}
}
思路2(使用数组)
1.首先定义一个长度为58的数组,用来统计各个字符出现的次数(A的ascii码为65,z的ascii码为122,122-65=57, 故数组长度为58)。
2.遍历字符串,将遍历出来的每一个字符减65做为索引值,该索引值对应的元素用来存放该字符出现的次数
3.遍历字符串同时遍历数组,判断当前遍历的字符出现次数是否为1
import java.util.*;
public class Solution {
public int FirstNotRepeatingChar(String str) {
if(str == null || str.length() == 0)
return -1;
int arr[] = new int[58];
for(int i=0; i<str.length(); i++){
arr[str.charAt(i) - 'A'] += 1;
}
for(int i=0; i<str.length(); i++){
if(arr[str.charAt(i) - 'A'] == 1)
return i;
}
return -1;
}
}