哈希表:O(1)查找的终极指南

一、哈希表核心思想

哈希表又称散列表,核心逻辑:通过哈希函数,把关键字直接映射到数组下标 实现近乎 O(1) 时间复杂度的查找、插入、删除。

普通数组:按下标找值哈希表:按值直接找存储位置

二、哈希函数作用

公式:存储下标 = hash(关键字)设计原则:

  1. 计算速度快
  2. 映射分布均匀,减少扎堆
  3. 尽量减少重复映射结果

常用简单哈希:取模运算

复制代码
hash(key) = key % 数组长度

三、哈希冲突

不同关键字,经过哈希函数算出同一个下标,即为哈希冲突。例如:长度为 10 数组,11 和 21 取模结果一致。

无法彻底避免,只能高效解决

四、两大主流冲突解决方式

1. 开放定址法

冲突后向后寻找空闲位置存放

  • 线性探测:往后逐个遍历空位
  • 二次探测:跳跃式寻找缺点:容易产生数据聚集,查找效率下降

2. 链地址法(拉链法)【工程最常用】

数组每个位置挂一条链表

  • 映射下标相同的元素,全部挂载在同一条链表上
  • 查询时先定位数组下标,再遍历短链表查找
  • C++ unordered_map/unordered_set 底层默认采用拉链法

五、负载因子

负载因子 = 元素个数 / 哈希表容量负载因子越大,冲突越多、效率越低C++ 无序容器默认达到阈值自动扩容重新哈希

六、C++ 哈希容器分类

  1. unordered_set:无序集合,元素唯一,底层哈希表
  2. unordered_map:无序键值对,key 唯一,刷题最常用
  3. set/map:有序,底层红黑树,O (logn)

选型口诀

  • 只需要快速查找、去重、存取无序 → 用哈希表 unordered
  • 需要自动排序、有序遍历 → 用红黑树 map/set

七、unordered_map 全套刷题用法

头文件

复制代码
#include <unordered_map>
#include <iostream>
#include <string>
using namespace std;

基础增删改查

复制代码
int main()
{
    unordered_map<string,int> mp;

    // 插入
    mp["张三"] = 20;
    mp["李四"] = 22;
    mp.insert({"王五",19});

    // 取值
    cout << mp["张三"] << endl;

    // 修改
    mp["张三"] = 25;

    // 查找
    if(mp.find("李四") != mp.end())
    {
        cout << "存在该键" << endl;
    }

    // 删除
    mp.erase("王五");

    // 遍历
    for(auto& p : mp)
    {
        cout << p.first << " " << p.second << endl;
    }

    // 判空、大小
    mp.empty();
    mp.size();
    return 0;
}

八、经典刷题例题:两数之和

LeetCode 1 原题,哈希表经典秒杀模板

复制代码
#include <vector>
#include <unordered_map>
using namespace std;

vector<int> twoSum(vector<int>& nums, int target)
{
    unordered_map<int,int> hash;
    for(int i = 0; i < nums.size(); i++)
    {
        int need = target - nums[i];
        if(hash.find(need) != hash.end())
        {
            return {hash[need],i};
        }
        hash[nums[i]] = i;
    }
    return {};
}

思路:边遍历边存值,寻找互补数字,一次遍历完成。

九、哈希表优缺点

优点

  1. 查找插入删除平均 O (1),速度极快
  2. 适合海量数据快速匹配、统计频次

缺点

  1. 无序存储,无法有序遍历
  2. 存在哈希冲突,极端情况退化成链表 O (n)
  3. 内存占用相对更高

十、面试高频考点

  1. 哈希表为什么查询快?哈希映射直接定位下标
  2. 哈希冲突怎么解决?拉链法、开放定址法
  3. unordered_map 和 map 底层区别与效率差异
  4. 负载因子作用与自动扩容机制

十一、今日总结

  1. 哈希表依靠哈希函数实现 O (1) 级访问
  2. 拉链法是实际开发最主流冲突解决方案
  3. 刷题优先使用 unordered_map 做频次统计、配对查找
  4. 无序选哈希,有序选红黑树容器
相关推荐
幻奏岚音1 小时前
AI模型用户画像分析_new
人工智能·算法·计算机视觉·数据挖掘
阿Y加油吧1 小时前
二刷 LeetCode:爬楼梯与杨辉三角,Java 实现复盘
java·算法·leetcode
落羽的落羽1 小时前
【项目】C++从零实现JsonRpc框架——项目引入
linux·服务器·开发语言·c++·人工智能·算法·机器学习
凌波粒1 小时前
LeetCode--101. 对称二叉树(二叉树)
算法·leetcode·职场和发展
不知名的忻1 小时前
堆排序(Java)
java·数据结构·算法·排序算法
_深海凉_1 小时前
LeetCode热题100-二叉树的最大深度
算法·leetcode·职场和发展
智者知已应修善业2 小时前
【51单片机独立按键和定时器中断的疑惑验证】2023-11-2
c++·经验分享·笔记·算法·51单片机
折翅嘀皇虫2 小时前
【无标题】steal_work_thread_pool
服务器·前端·算法
zzzsde2 小时前
【Linux】线程概念与控制(3):线程ID&&C++封装线程
linux·运维·服务器·开发语言·算法