题目
思路1(HashMap)
利用HashMap,查询第一个只出现一次的字符,那么在第一轮循环字符串统计各个字符出现的次数,然后第二轮循环字符串,使用已经构建好的HashMap,当第一次找到出现次数为1时,返回该字符即可。
代码1
class Solution {
public char firstUniqChar(String s) {
HashMap<Character,Integer> hashmap=new HashMap<>();
//char res=' ';
for(int i=0;i<s.length();i++)
{
if(hashmap.containsKey(s.charAt(i)))
hashmap.put(s.charAt(i),hashmap.get(s.charAt(i))+1);
else
hashmap.put(s.charAt(i),1);
}
for(int i=0;i<s.length();i++)
{
if(hashmap.get(s.charAt(i))==1)
return s.charAt(i);
}
return ' ';
}
}
时间复杂度比较高,应该是在containsKey
那里花了比较多时间。
思路2 (26个小写字母)
由题目知,字符串中只含有小写字符,那么我们构建一个长度为26的字符数组,循环字符串一次用于统计次数,第二次循环字符串,找到数组中元素为1,即可根据下标返回该字符。
a-z对应97-122
因此创建数组arr[26],放置时根据字符(ch-97)即可将对应数组位置的值加1
代码2
class Solution {
public char firstUniqChar(String s) {
char arr[]=new char[26];
//a-z对应于97-122
for(int i=0;i<s.length();i++)
{
arr[s.charAt(i)-97]++;
}
for(int i=0;i<s.length();i++)
{
if(arr[s.charAt(i)-97]==1)
return s.charAt(i);
}
return ' ';
}
}
时间和空间都要优于方法1
思路3
还是利用HashMap
,但是这次HashMap
中的元素是Character
和Boolean
,之所以是Boolean
而不是Integer
,是因为我们在意的是第一个只出现一次的元素,因此其它元素出现几次我们并不关心,因此我们只需要使用一个Boolean
表示,true
则表示其出现了一次,false
则表示出现不止一次。
具体实现如下:
使用containsKey()
函数,因为其返回值是Boolean
类型,
一开始,元素不存在,我们第一次填入,因此Boolean
为true
后面再填入相同的元素时,由于元素已经存在,因此Boolean
为false
hashmap.put(arr[i],!hashmap.containsKey(arr[i]));
仔细体会这一段代码,可以自己举例帮助理解,相信你一定能理解这段代码的巧妙之处^ ^
代码3
class Solution {
public char firstUniqChar(String s) {
HashMap<Character,Boolean> hashmap=new HashMap<>();
char arr[]=s.toCharArray();
for(int i=0;i<arr.length;i++)
{
hashmap.put(arr[i],!hashmap.containsKey(arr[i]));
}
for(int i=0;i<arr.length;i++)
{
if(hashmap.get(arr[i]))
return arr[i];
}
return ' ';
}
}