长沙小吃培训哪里学靠谱:长沙曾食坊小吃培训的核验清单
2026/10/4 7:42:18
在处理字符串处理类算法题时,“频率统计”是一个核心思想。今天我们将通过LeetCode 387. 字符串中的第一个唯一字符这道经典题目,深入探讨两种主流解法:数组映射法与HashMap 计数法。
给定一个字符串s,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回-1。
示例:
s = "leetcode"-> 输出:0s = "loveleetcode"-> 输出:2s = "aabb"-> 输出:-1提示:
s只包含小写字母。无论是使用数组还是 HashMap,其核心逻辑都是相同的,即**“空间换时间”**。
classSolution{publicintfirstUniqChar(Strings){// 因为小写字母 ASCII 码或扩展 ASCII 范围内,256 足够覆盖int[]count=newint[256];// 1. 统计频率for(inti=0;i<s.length();i++){count[s.charAt(i)]++;}// 2. 查找第一个频率为 1 的字符索引for(inti=0;i<s.length();i++){if(1==count[s.charAt(i)])returni;}return-1;}}int[26]的数组,通过s.charAt(i) - 'a'将字符映射到 0-25 索引。使用int[256]更加通用,可以处理所有标准 ASCII 字符。classSolution{publicintfirstUniqChar(Strings){// 使用 HashMap 存储字符及其出现次数HashMap<Character,Integer>count=newHashMap<>();// 1. 统计频率for(inti=0;i<s.length();i++){charc=s.charAt(i);// 如果不存在则存入1,存在则在原值基础上+1count.put(c,count.getOrDefault(c,0)+1);}// 2. 查找第一个频率为 1 的字符索引for(inti=0;i<s.length();i++){if(count.get(s.charAt(i))==1)returni;}return-1;}}HashMap的键值对(Key-Value)结构。Key 存储字符Character,Value 存储该字符出现的次数Integer。count.getOrDefault(c, 0) + 1是一个优雅的写法,它代替了if(!containsKey)的条件判断,使代码更简洁。(虽然也可以使用HashMap的containsKey方法来检测是不是已经有了某个字符,但getOrDefault方法明显更加先进,直接内含了判断字符是否存在的逻辑,是就返回value(题中代码是返回的value+1),不存在就返回默认value(0)(题中代码在key不存在时,首次加入key的value也是0+1))HashMap可以轻松应对。| 维度 | 解法一:数组 (Array) | 解法二:HashMap |
|---|---|---|
| 时间复杂度 | O(N)O(N)O(N)- 遍历两次字符串 | O(N)O(N)O(N)- 遍历两次字符串 |
| 空间复杂度 | O(1)O(1)O(1)- 固定大小 (256 或 26) | O(1)O(1)O(1)或O(k)O(k)O(k)- 字符集大小 |
| 实际效率 | 极高(直接内存访问) | 一般(涉及对象开销、哈希计算) |
| 适用场景 | 字符范围固定(如仅字母/ASCII) | 字符范围未知或非常分散(如全 Unicode) |
在 Java 中,HashMap需要对基本类型进行装箱(int转Integer),并且在计算哈希槽、处理链表或红黑树结构时有额外的计算开销。而数组是连续的内存空间,CPU 缓存命中率更高。
核心套路牢记:凡是涉及“第一个唯一”、“重复元素”、“频率统计”的问题,空间换时间(哈希思想)永远是你的首选策略!