Skip to content

哈希表经典应用

场景引入

哈希表是面试中使用频率最高的数据结构之一。它的核心能力就一个:O(1) 查找。大量看似复杂的问题,加上哈希表就能从 O(n²) 降到 O(n)。

LC 1. 两数之和

给定数组 nums 和目标值 target,找到两个数使其和为 target,返回下标。

暴力:O(n²)

javascript
for (let i = 0; i < nums.length; i++)
  for (let j = i + 1; j < nums.length; j++)
    if (nums[i] + nums[j] === target) return [i, j];

哈希表:O(n)

javascript
function twoSum(nums, target) {
  const map = new Map();
  for (let i = 0; i < nums.length; i++) {
    const complement = target - nums[i];
    if (map.has(complement)) {
      return [map.get(complement), i];
    }
    map.set(nums[i], i);
  }
  return [];
}

关键思路:遍历时边查边存,用哈希表记录「我需要的那个数」是否已经出现过。

LC 49. 字母异位词分组

给定字符串数组,将字母异位词分组。如 ["eat","tea","ate"] → [["eat","tea","ate"]]

javascript
function groupAnagrams(strs) {
  const map = new Map();
  for (const s of strs) {
    const key = [...s].sort().join('');
    if (!map.has(key)) map.set(key, []);
    map.get(key).push(s);
  }
  return [...map.values()];
}

关键思路:字母异位词排序后相同,用排序后的字符串作为哈希表的 key。

LC 128. 最长连续序列

给定未排序数组,找出最长连续元素序列的长度。要求 O(n) 时间。

javascript
function longestConsecutive(nums) {
  const set = new Set(nums);
  let maxLen = 0;

  for (const num of set) {
    // 只从序列起点开始计数
    if (!set.has(num - 1)) {
      let current = num;
      let len = 1;
      while (set.has(current + 1)) {
        current++;
        len++;
      }
      maxLen = Math.max(maxLen, len);
    }
  }
  return maxLen;
}

关键思路:用 Set 实现 O(1) 查找。只从每个序列的起点(没有 num-1 的数)开始计数,避免重复计算。

LC 380. O(1) 时间插入、删除和获取随机元素

javascript
class RandomizedSet {
  constructor() {
    this.map = new Map(); // val -> index
    this.list = [];
  }

  insert(val) {
    if (this.map.has(val)) return false;
    this.map.set(val, this.list.length);
    this.list.push(val);
    return true;
  }

  remove(val) {
    if (!this.map.has(val)) return false;
    const idx = this.map.get(val);
    const last = this.list[this.list.length - 1];
    this.list[idx] = last;
    this.map.set(last, idx);
    this.list.pop();
    this.map.delete(val);
    return true;
  }

  getRandom() {
    const idx = Math.floor(Math.random() * this.list.length);
    return this.list[idx];
  }
}

关键思路:HashMap + 数组。删除时将目标与末尾元素交换,然后 pop,保证 O(1)。

哈希表的通用模式

模式说明例题
查找配对用哈希表存已遍历元素,查找互补值LC 1
分组归类用特征值作 key,同类元素归到同一组LC 49
去重计数用 Set/Map 记录出现情况LC 128
索引映射维护值到下标的映射,支持 O(1) 定位LC 380

复杂度分析

所有上述解法时间复杂度均为 O(n),空间复杂度 O(n)

LeetCode 练习

  • LC 1. 两数之和 ⭐
  • LC 49. 字母异位词分组 ⭐
  • LC 128. 最长连续序列 ⭐
  • LC 380. O(1) 时间插入、删除和获取随机元素
  • LC 242. 有效的字母异位词
  • LC 349. 两个数组的交集

面试算法可视化图解