34. 第一个只出现一次的字符
思路一:计数排序
由于限定了所有字符为字母,所以可以统计每个字符出现的次数,然后第二次遍历字符串,判断每个字符出现的次数,找到第一个次数为一的返回即可
这里计数数组长度设置为 58, 是因为 大写字符的 ASCII 范围为 65 - 90, 小写字符的ASCII 范围为 97 - 122,所以从 65 - 122 共58个单位长度
public class Solution {
public int FirstNotRepeatingChar(String str) {
// 计数排序
// 数组长度只需 58即可 112 - 65 + 1 = 58
int[] count = new int[58];
for(int i = 0; i < str.length(); i++){
count[str.charAt(i) - 'A']++;
}
// 再次遍历 str 字符串,找到第一个字符对应的个数为1即可
for(int i = 0; i < str.length(); i++){
if(count[str.charAt(i) - 'A'] == 1){
return i;
}
}
return -1;
}
}
复杂度分析:
时间复杂度:最多遍历两次字符串,所以时间复杂度为O(n)
空间复杂度:借助了一个长度为58的数组,是常量级的,所以空间复杂度为O(1)
注:
Java 中的字符在于整数做加减运算的时候也会转换成 ASCII 来做运算,所以可以作为下标来使用。
leetcode 剑指 Offer 50. 第一个只出现一次的字符
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例:
s = "abaccdeff"
返回 "b"
s = ""
返回 " "
思路一:同上思路一,使用计数排序实现
1 class Solution {
2 public char firstUniqChar(String s) {
3 // 先使用计数排序统计每个字符出现的次数
4 int[] counts = new int[26];
5 int len = s.length();
6 for(int i = 0; i < len; i++){
7 counts[s.charAt(i) - 'a']++;
8 }
9
10 // 然后再次遍历字符串,判断每个字符出现的次数,返回第一个次数为1的字符
11 for(int i = 0; i < len; i++){
12 if(counts[s.charAt(i) - 'a'] == 1){
13 return s.charAt(i);
14 }
15 }
16
17 return ' ';
18 }
19 }
leetcode 运行时间为8ms, 空间为39.4MB
复杂度分析:
时间复杂度:最多遍历两次字符串,所以时间复杂度为O(2n)
空间复杂度:需要一个大小为26的数组,但是大小时产量级的,所以空间复杂度为O(1)
思路二:使用LinkedHashMap这个有序 hash表实现
LinkedHashMap不仅可以统计出现次数,还可以维护一个插入顺序,所以减少了第二次扫描字符串的开销
1 class Solution {
2 public char firstUniqChar(String s) {
3 // 先使用计数排序统计每个字符出现的次数
4 LinkedHashMap<Character, Boolean> map = new LinkedHashMap<>();
5 int len = s.length();
6 for(int i = 0; i < len; i++){
7 map.put(s.charAt(i), !map.containsKey(s.charAt(i))); // 如果重复则置为false
8 }
9
10 // 遍历map,因为mp的大小最大为26, 所以这次循环的时间复杂度为O(1)
11 for(Map.Entry<Character, Boolean> en : map.entrySet()){
12 if(en.getValue() == true){
13 return en.getKey();
14 }
15 }
16
17 return ' ';
18 }
19 }
leetcode运行时间为:38ms, 时间为39.5MBb, 根据前面思路介绍的,案例来说这个时间应该比思路一快才对,但是事实就是慢这么多,我觉得应该是思路一用的是数组来计数,所以效率较高,但是如果使用hashmap来计数的话,那时间上应该会比当前解法慢
复杂度分析:
时间复杂度:遍历了一次字符串,花费时间为O(n), 虽然后面还是有一个遍历map的循环,但是循环次数最多为26次,可以忽略不计,所以总的时间复杂度为O(n)
空间复杂度:借用了一个大小为26的 LinkedHashMap, 常量级别的,所以空间复杂度为O(1)