哈希

unordered_map基础概念

  • 哈希表容器unordered_map 使用哈希函数将键映射到桶中,从而实现高效的键值对存储和查找。
  • 键值对存储:每个元素由一个键 (key) 和一个值 (value) 组成,键用于快速访问对应的值。
  • 无序:键值对存储在哈希表中,不保证元素的顺序。
  • 常用操作复杂度:插入、查找和删除操作的平均时间复杂度为 O(1)O(1)。

1. 类型声明 unordered_map<int, int>

  • 键类型 (int):键是一个整数类型。
  • 值类型 (int):值也是一个整数类型。

2. 如何理解 unordered_map<int, int> hashmap;

  • 类型声明:声明了一个名为 hashmapunordered_map 对象,键和值均为整型 (int)。
  • 默认初始化:此对象在创建时,内部无任何键值对。

3. 常用操作

以下是对 unordered_map 的常见操作及示例:

1. 插入元素

cppCopy codehashmap[1] = 10;       // 插入键值对 {1, 10}
hashmap[2] = 20;       // 插入键值对 {2, 20}
hashmap.insert({3, 30}); // 另一种插入方式

2. 访问元素

cppCopy codestd::cout << hashmap[1];    // 输出 10
std::cout << hashmap.at(2); // 输出 20

注意:使用 at() 方法时,如果键不存在会抛出异常,而 [] 运算符会插入一个默认值。

3. 查找元素

cppCopy codeif (hashmap.find(1) != hashmap.end()) {
    std::cout << "Key 1 exists!" << std::endl;
}

4. 删除元素

cpp


Copy code
hashmap.erase(1); // 删除键为 1 的元素

5. 遍历元素

cppCopy codefor (const auto &pair : hashmap) {
    std::cout << pair.first << ": " << pair.second << std::endl;
}

代码完整示例

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<int, int> hashmap;

    // 插入元素
    hashmap[1] = 10;
    hashmap[2] = 20;

    // 遍历元素
    for (const auto &pair : hashmap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 查找元素
    if (hashmap.find(1) != hashmap.end()) {
        std::cout << "Key 1 found with value: " << hashmap[1] << std::endl;
    }

    // 删除元素
    hashmap.erase(1);

    return 0;
}

运行结果可能为:

yamlCopy code1: 10
2: 20
Key 1 found with value: 10

unordered_set 的特性:基本概念

  1. 唯一性
    • std::unordered_set 中的所有元素都是唯一的,重复插入相同的元素会被忽略。
  2. 无序存储
    • 元素存储顺序不固定,具体顺序由哈希函数决定。
  3. 高效操作
    • 插入、查找和删除的平均时间复杂度为 O(1)O(1)。
    • 最差情况下(哈希冲突严重),复杂度可能退化为 O(N)O(N)。
  4. 底层实现
    • 使用哈希表(Hash Table)存储数据,通过哈希函数对元素进行分布和管理。
  5. 键值即元素
    • std::unordered_set 的每个元素本身既是键,也是值。

1.语法:

cppCopy code#include <unordered_set>
std::unordered_set<T> set_name;
  • T:元素类型。
  • 默认构造函数:创建一个空集合。

2. 常见操作

操作函数或方法说明
插入元素insert(value)value 插入集合,如果 value 已存在,则插入失败。
查找元素find(value)返回迭代器,指向 value 所在的位置;如果找不到,返回 end()
删除元素erase(value)删除值为 value 的元素,如果不存在,则不执行任何操作。
获取大小size()返回集合中元素的数量。
清空集合clear()删除集合中所有元素。
检查是否存在count(value)find(value)判断 value 是否存在,返回布尔值(count 返回 0 或 1)。
遍历集合使用范围循环或迭代器遍历集合中所有元素。
桶操作bucket_count(), bucket_size()查看哈希表的桶数量或某个桶中元素的数量,用于观察哈希分布情况。

3. 示例代码

#include <iostream>
#include <unordered_set>

int main() {
    // 创建 unordered_set
    std::unordered_set<int> mySet;

    // 插入元素
    mySet.insert(10);
    mySet.insert(20);
    mySet.insert(10); // 重复元素不会插入

    // 查找元素
    if (mySet.find(10) != mySet.end()) {
        std::cout << "10 exists in the set." << std::endl;
    }

    // 遍历元素
    std::cout << "Set elements: ";
    for (const int &val : mySet) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    // 删除元素
    mySet.erase(20);

    // 检查集合大小
    std::cout << "Set size after deletion: " << mySet.size() << std::endl;

    return 0;
}

输出:

arduinoCopy code10 exists in the set.
Set elements: 10 20 
Set size after deletion: 1

4. 使用场景

std::unordered_set 适用于以下场景:

  1. 快速查找
    • 判断某个值是否存在,如单词检查、集合操作等。
  2. 去重
    • 只存储唯一值,例如移除重复数据。
  3. 高效处理大数据
    • 在需要快速插入和查找的场景下表现优越。

Leetcode

1. 两数之和

  • 使用哈希表存储每一个元素
  • 运用逆向思维 , int x = target - nums[i] , 找到匹配值

49. 字母异位词分组

128. 最长连续序列

  • 注意是连续数值
  • 只需要枚举每一段的开头
  • 除了不是开头端点, 其他的点要从哈希表中删除