欢迎光临
我们一直在努力

哈希表算法通关指南:拆解 LeetCode 两大经典模型

哈希表(HashMap)算法总结

本文总结 LeetCode 上两道经典哈希表题目:两数之和 与 字母异位词分组。


一、两数之和(Two Sum)

题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那两个整数,并返回它们的数组下标。

假设每种输入只会对应一个答案,且不能使用同一个元素两次。

示例:

输入:nums = [2, 7, 11, 15], target = 9
输出:[0, 1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1]

核心思路

暴力解法需要两层循环,时间复杂度 O(n²)。使用哈希表可以将时间复杂度降到 O(n)。

思想:遍历数组时,计算当前元素与目标值的差值 needNum = target – nums[i],检查这个差值是否已经存在于哈希表中:

  • 如果存在 → 说明之前遍历过的某个元素 + 当前元素 = target,直接返回两个下标。
  • 如果不存在 → 将当前元素的值和下标存入哈希表,继续遍历。

Java 代码

import java.util.HashMap;

class Solution {
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> maps = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int needNum = target nums[i];
if (maps.containsKey(needNum)) {
return new int[]{maps.get(needNum), i};
}
maps.put(nums[i], i);
}
return new int[]{};
}
}

复杂度分析

复杂度值
时间复杂度 O(n) — 只需一次遍历
空间复杂度 O(n) — 哈希表最多存储 n 个元素

关键点

  • HashMap 的 key 存值,value 存下标:因为要根据差值快速查找对应的下标。
  • 先检查再存入:保证不会重复使用同一个元素(同一个元素只能使用一次)。
  • 返回 new int[]{} 作为兜底,虽然题目保证一定有解。

二、字母异位词分组(Group Anagrams)

题目描述

给你一个字符串数组,请你将 字母异位词 组合在一起,返回结果列表。

字母异位词:由相同字母重新排列形成的字符串。例如 "eat" 和 "tea" 是字母异位词。

示例:

输入:strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出:[["bat"], ["nat", "tan"], ["ate", "eat", "tea"]]

核心思路

核心在于如何判断两个字符串是否为字母异位词。本质上是找到一种 统一的特征(key),让所有字母异位词映射到同一个 key 上。

方法:排序法

将每个字符串按字母排序,字母异位词排序后会得到完全相同的字符串。以这个排序后的字符串作为 key,将原始字符串归入对应的组。

Java 代码

import java.util.*;

class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
HashMap<String, List<String>> map = new HashMap<>();
for (String s : strs) {
char[] arr = s.toCharArray();
Arrays.sort(arr);
String key = new String(arr);
map.computeIfAbsent(key, k -> new ArrayList<>());
map.get(key).add(s);
}
return new ArrayList<>(map.values());
}
}

复杂度分析

复杂度值
时间复杂度 O(n × k log k) — n 个字符串,每个长 k,排序 O(k log k)
空间复杂度 O(n × k) — 存储所有字符串

关键点

  • toCharArray() 将字符串转为字符数组,方便排序。

  • Arrays.sort(arr) 对字符数组排序,字母异位词排序后完全相同。

  • computeIfAbsent(key, k -> new ArrayList<>()):如果 key 不存在则创建新列表,存在则直接返回已有的列表。这行等价于:

    if (!map.containsKey(key)) {
    map.put(key, new ArrayList<>());
    }
    map.get(key).add(s);

  • 最后通过 new ArrayList<>(map.values()) 直接从 HashMap 的 values 构造结果列表。


三、哈希表解题模板总结

什么时候用哈希表?

场景说明
快速查找 需要频繁判断某个元素是否存在,O(1) 查找
去重 / 计数 统计元素出现次数
分组 / 映射 建立键值对关系,将同类数据归组
降低复杂度 把 O(n²) 的双重循环优化到 O(n)

常用技巧

技巧说明
值→下标 用 HashMap 存值和索引(如两数之和)
特征→分组 将数据按某种特征(key)分组(如字母异位词分组)
computeIfAbsent 简化 “不存在则新建” 的逻辑
getOrDefault 计数场景常用,不存在时返回默认值

四、小结

这两道题分别代表了哈希表最常见的两种应用场景:

  • 两数之和 → 用 HashMap 做 快速查找(值 → 下标),将暴力 O(n²) 优化到 O(n)。
  • 字母异位词分组 → 用 HashMap 做 分组归类(排序后的 key → 同组字符串列表)。
  • 赞(0)
    未经允许不得转载:171主机测评 » 哈希表算法通关指南:拆解 LeetCode 两大经典模型
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址