第5天:哈希表基础 学习目标
掌握哈希表的基本操作和特性
熟练解决两数之和、三数之和问题
理解字符串哈希和字符计数
学会滑动窗口+哈希表的组合技巧
哈希表基础概念 哈希表特点
查找效率 :O(1) 平均时间复杂度
空间换时间 :用额外空间换取查找速度
键值对存储 :通过键快速查找值
去重功能 :自动处理重复元素
哈希表常用操作
insert(key, value)
:插入键值对
find(key)
:查找键对应的值
erase(key)
:删除键值对
count(key)
:统计键的出现次数
C++中的哈希表
unordered_map
:无序映射,基于哈希表
unordered_set
:无序集合,基于哈希表
map
:有序映射,基于红黑树
set
:有序集合,基于红黑树
今日重点题目 1. 两数之和 (Easy) 题目链接: 1. 两数之和
题目描述: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
解题思路: 使用哈希表存储已遍历的元素和其索引,对于当前元素,查找target-nums[i]是否在哈希表中。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution {public : vector<int > twoSum (vector<int >& nums, int target) { unordered_map<int , int > numToIndex; for (int i = 0 ; i < nums.size (); i++) { int complement = target - nums[i]; if (numToIndex.find (complement) != numToIndex.end ()) { return {numToIndex[complement], i}; } numToIndex[nums[i]] = i; } return {}; } };
时间复杂度: O(n)空间复杂度: O(n)
2. 无重复字符的最长子串 (Medium) 题目链接: 3. 无重复字符的最长子串
题目描述: 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
解题思路: 滑动窗口+哈希表,维护一个不包含重复字符的窗口,用哈希表记录字符在窗口中的位置。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Solution {public : int lengthOfLongestSubstring (string s) { unordered_map<char , int > charToIndex; int left = 0 , maxLen = 0 ; for (int right = 0 ; right < s.length (); right++) { if (charToIndex.find (s[right]) != charToIndex.end () && charToIndex[s[right]] >= left) { left = charToIndex[s[right]] + 1 ; } charToIndex[s[right]] = right; maxLen = max (maxLen, right - left + 1 ); } return maxLen; } };
时间复杂度: O(n)空间复杂度: O(min(m, n)),m是字符集大小
3. 字母异位词分组 (Medium) 题目链接: 49. 字母异位词分组
题目描述: 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列字母得到的单词,所有源单词中的字母通常恰好只用一次。
解题思路: 将每个字符串排序后作为键,相同键的字符串归为一组。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : vector<vector<string>> groupAnagrams (vector<string>& strs) { unordered_map<string, vector<string>> groups; for (const string& str : strs) { string key = str; sort (key.begin (), key.end ()); groups[key].push_back (str); } vector<vector<string>> result; for (auto & pair : groups) { result.push_back (pair.second); } return result; } };
时间复杂度: O(nk log k),k是字符串平均长度空间复杂度: O(nk)
4. 最长连续序列 (Medium) 题目链接: 128. 最长连续序列
题目描述: 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
解题思路: 使用哈希表存储所有数字,对于每个数字,检查其连续序列的长度。
代码实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution {public : int longestConsecutive (vector<int >& nums) { unordered_set<int > numSet (nums.begin(), nums.end()) ; int maxLen = 0 ; for (int num : numSet) { if (numSet.find (num - 1 ) == numSet.end ()) { int currentNum = num; int currentLen = 1 ; while (numSet.find (currentNum + 1 ) != numSet.end ()) { currentNum++; currentLen++; } maxLen = max (maxLen, currentLen); } } return maxLen; } };
时间复杂度: O(n)空间复杂度: O(n)
滑动窗口+哈希表 滑动窗口模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int slidingWindow (string s) { unordered_map<char , int > window; int left = 0 , right = 0 ; int result = 0 ; while (right < s.length ()) { char c = s[right]; window[c]++; right++; while (window needs shrink) { char d = s[left]; window[d]--; left++; } result = max (result, right - left); } return result; }
字符串哈希技巧 字符计数 1 2 3 4 5 unordered_map<char , int > charCount; for (char c : s) { charCount[c]++; }
字符频率比较 1 2 3 4 5 6 7 8 9 10 11 12 bool isAnagram (string s, string t) { if (s.length () != t.length ()) return false ; unordered_map<char , int > count; for (char c : s) count[c]++; for (char c : t) { count[c]--; if (count[c] < 0 ) return false ; } return true ; }
扩展练习 5. 三数之和 (Medium) 题目链接: 15. 三数之和
6. 四数之和 (Medium) 题目链接: 18. 四数之和
7. 有效的字母异位词 (Easy) 题目链接: 242. 有效的字母异位词
8. 赎金信 (Easy) 题目链接: 383. 赎金信
学习总结 哈希表解题要点
键的选择 :选择合适的键类型和值
查找优化 :利用哈希表O(1)查找特性
去重处理 :利用哈希表自动去重
空间权衡 :考虑空间复杂度的合理性
滑动窗口+哈希表
窗口维护 :保持窗口内元素满足条件
边界处理 :正确处理窗口的扩大和收缩
状态更新 :及时更新哈希表中的状态
结果计算 :在合适的时机计算最终结果
字符串哈希技巧
字符计数 :统计字符频率
模式匹配 :利用哈希表快速匹配
去重处理 :处理重复字符问题
排序优化 :利用排序简化比较
常见错误
哈希表键类型选择错误
滑动窗口边界处理不当
字符串比较时忽略大小写
内存泄漏(C++中)
今日收获
掌握了哈希表的基本应用
学会了滑动窗口+哈希表的组合
理解了字符串哈希的技巧
建立了哈希表解题的思维模式
明日预告 明天我们将学习哈希表进阶内容,包括双指针+哈希表、前缀和+哈希表等更复杂的应用。
返回周计划 | 上一题:树结构进阶 | 下一题:哈希表进阶