问题描述:
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例:
s = "abaccdeff"
返回 "b"
s = ""
返回 " "
解题思路:
解法一:双层遍历,set记录
使用遍历字符串的方式进行解题,不过再遍历的过程中可以用set作记录提高效率。每当遍历到一个新的字符时,就将其存储到set中;如果set中已经有当前字符,则说明当前字符出现过,直接continue;如果是新字符则向后遍历看其是否只出现一次。
解法二:使用哈希表记录
遍历字符串,使用哈希表统计各个字符出现的次数是否大于1。再一次遍历字符串找到第一个出现次数为1的字符。
代码实现:
解法一代码:
public static char firstUniqChar(String s) {
Set<Character> set = new HashSet<Character>(); //用于存储出现过的字符
l1:for(int i=0; i<s.length(); i++) {
char t = s.charAt(i);
if( set.contains(t) ) {
continue;
}
set.add(t); //添加新出现的字符
for(int j=i+1; j<s.length(); j++) {
if(t==s.charAt(j)) //说明t不止出现一次
continue l1; //结束本次的外层循环
}
return t; //t只出现一次,将结果返回
}
return ' '; //没有则返回空格
}
解法一提交结果:
解法二代码:
public static char firstUniqChar2(String s) {
//可以使用true和false进行统计出现的次数是否为1
HashMap<Character, Boolean> map = new HashMap<Character, Boolean>();
for(int i=0; i<s.length(); i++) {
map.put(s.charAt(i), !map.containsKey(s.charAt(i))); //中有只出现一次的字符的value才会是true
}
for(int i=0; i<s.length(); i++) {
if(map.get(s.charAt(i))) //寻找第一个为true的字符,即第一个只出现一次的字符
return s.charAt(i);
}
return ' ';
}
解法二提交结果:
总结:解法一看上去效率更低,但是当字符重复地比较多时,解法一的效率反而更高。由于题目给出的字符串只包含小写字符,即可能出现的字符只有26个。当字符串很长时,重复的字符会很多,解法一的效率就会很高;因为解法一最多进行26次双重循环,其余情况都能直接跳过循环。