剑指offer:第一个只出现一次的字符
题意描述
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
解题思路
一、思路一
-
遍历字符串,使用HashMap记录每个字符出现的次数。
-
再次遍历字符串,从map中查找每个字符出现的次数,返回第一个
value == 1
的索引。
import java.util.*;
public class Solution {
public int FirstNotRepeatingChar(String str) {
if(str == null || str.length() == 0) return -1;
HashMap<Character,Integer> map = new HashMap<>();
for(int i=0;i<str.length();i++){
if (map.containsKey(str.charAt(i))) //map中存在字符,value++
map.put(str.charAt(i), map.get(str.charAt(i)) + 1);
else
map.put(str.charAt(i), 1); //初次出现,将字符加入map
}
for(int i=0;i<str.length();i++){
if(map.get(str.charAt(i)) == 1){
return i; //返回索引
}
}
return 0;
}
}
每次添加之前都要在map中查询字符是否存在,会消耗大量时间,能否进行优化呢?
因为字符串中只存在字母,所以可以使用一个char类型的数组,对应从A-z
的每个字符,如果出现字符,直接对相应的索引+1。这样可以省去查询map的开销。
public class Solution {
public int FirstNotRepeatingChar(String str) {
char[] chars = str.toCharArray();
//使用一个‘z’+1大小的数组
//65 - 90 表示 A - Z
//97 - 122 表示 a - z
char[] arr = new char['z' + 1];
for (char c : chars) {
arr[c]++; //每出现依次,对应的索引值+1
}
for (int i = 0; i < chars.length; i++) {
if (arr[chars[i]] == 1) { //查找第一个数组值为1的
return i;
}
}
return -1;
}
}