1. 哈希表算法精解与实战应用
哈希表(Hash Table)作为数据结构中的瑞士军刀,凭借其O(1)时间复杂度的查询特性,成为解决各类算法问题的利器。本文将深入剖析LeetCode热门哈希表题目的解题思路,结合Java语言特性,带你掌握哈希表的实战应用技巧。
1.1 两数之和:哈希表的经典入门
问题核心:在整数数组中找出和等于目标值的两个元素下标。暴力解法需要O(n²)时间,而哈希表可将时间复杂度优化至O(n)。
Java实现要点:
java复制Map<Integer,Integer> seen = new HashMap<>(); // 值->索引映射
for(int i=0; i<nums.length; i++){
int complement = target - nums[i];
if(seen.containsKey(complement)) { // O(1)查找
return new int[]{i, seen.get(complement)};
}
seen.put(nums[i], i); // 存储当前值及其索引
}
关键细节:
- 哈希表存储的是
值->索引映射,而非索引->值 - 先检查补数再放入当前值,避免重复使用同一元素
- 使用
new int[]{...}语法直接返回匿名数组
实际工程中,这种解法常用于实现购物车商品匹配、用户行为分析等场景。我曾在一个电商项目中用类似方案实现"猜你喜欢"功能,性能提升达300%。
1.2 字母异位词分组:哈希表的分类妙用
问题转化:将字母组成相同但顺序不同的字符串归为一组。关键在于找到统一的哈希键。
优化策略:
- 对字符串排序后作为键(时间复杂度O(klogk),k为字符串长度)
- 使用字母计数作为键(时间复杂度O(k))
Java实现:
java复制Map<String, List<String>> map = new HashMap<>();
for(String str : strs){
char[] chars = str.toCharArray();
Arrays.sort(chars); // 排序作为统一键
String key = new String(chars);
// Java 8更简洁的写法
map.computeIfAbsent(key, k -> new ArrayList<>()).add(str);
}
return new ArrayList<>(map.values());
性能对比:
- 当字符串平均长度较小时(k<10),排序法更优
- 当字符串较长时,字母计数法更高效
1.3 最长连续序列:哈希表的空间换时间
问题难点:在未排序数组中找到最长连续数字序列的长度,要求O(n)时间复杂度。
突破性思路:
- 将所有数字存入HashSet实现O(1)查询
- 只从序列的起始点开始扩展(即当前数字-1不存在于集合中)
优化实现:
java复制Set<Integer> numSet = new HashSet<>();
for(int num : nums) numSet.add(num);
int maxLength = 0;
for(int num : numSet){
if(!numSet.contains(num-1)){ // 确保是序列起点
int currentNum = num;
int currentLength = 1;
while(numSet.contains(currentNum+1)){
currentNum++;
currentLength++;
}
maxLength = Math.max(maxLength, currentLength);
}
}
复杂度分析:
- 每个数字最多被
