数据结构-哈希表I

哈希表理论基础

常见的三种哈希结构

当我们想使用哈希法来解决问题的时候,我们一般会选择如下三种数据结构。

  • 数组

  • set (集合)

  • map(映射)

在C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示:

集合

底层实现

是否有序

数值是否可以重复

能否更改数值

查询效率

增删效率

std::set

红黑树

有序

O(log n)

O(log n)

std::multiset

红黑树

有序

O(logn)

O(logn)

std::unordered_set

哈希表

无序

O(1)

O(1)

std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。

映射

底层实现

是否有序

数值是否可以重复

能否更改数值

查询效率

增删效率

std::map

红黑树

key有序

key不可重复

key不可修改

O(logn)

O(logn)

std::multimap

红黑树

key有序

key可重复

key不可修改

O(log n)

O(log n)

std::unordered_map

哈希表

key无序

key不可重复

key不可修改

O(1)

O(1)

总结一下,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法

但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。

哈希表-有效的字母异位词

题目链接

哈希结构:数组

//Hash哈希表-有效的字母异位词
#include<bits/stdc++.h>
using namespace std;
string s, t;
int Hash[30], temp;
int main(){
    cin >> s >> t;
    for (int i = 0; i < s.size(); i++){
        Hash[s[i] - 'a']++;
    }
    for (int i = 0; i < t.size(); i++){
        Hash[t[i] - 'a']--;
    }
    for (int i = 0; i <= 26; i++){
        if (Hash[i] != 0){
            printf("false\n");
            temp = 1;
            break;
        }
    }
    if (temp == 0){
        printf("true\n");
    }
    return 0;
}

哈希表-两个数组的交集

题目链接

哈希结构:unordered_set

//Hash哈希表-两个数组的交集
#include<bits/stdc++.h>
using namespace std;
unordered_set<int> se;
unordered_set<int> ans_set;
int n, m;
int nums1[1000], nums2[1000];
int main(){
    cin >> n >> m;
    for (int i = 0; i < n; i++){
        cin >> nums1[i];
        se.insert(nums1[i]);
    }
    for (int i = 0; i < m; i++){
        cin >> nums2[i];
    }
    for (int num : nums2){
        if (se.find(num) != se.end()){
            ans_set.insert(num);
        }
    }
    for (auto it = ans_set.begin(); it != ans_set.end(); it++){
        printf("%d ", *it);
    }
    return 0;
}

哈希表-快乐数

题目链接

哈希结构:unordered_set

//Hash哈希表-快乐数
#include<bits/stdc++.h>
using namespace std;
unordered_set<int> ans_set;
int n, temp;
int getSum(int n){
    int sum = 0;
    while (n){
        sum += (n % 10) * (n % 10);
        n /= 10;
    }
    return sum;
}
bool judgeNum(int n){
    while (true){
        temp = getSum(n);
        if (temp == 1){
            return 1;
        }
        else {
            if (ans_set.find(temp) != ans_set.end()){
                return 0;
            }
            else {
                ans_set.insert(temp);
            }
        }
        n = temp;
    }
}
int main(){
    while (cin >> n){
        if (judgeNum(n)){
            printf("true\n");
        }
        else {
            printf("false\n");
        }
    }
    return 0;
}

哈希表-两数之和

题目链接

哈希结构:unordered_map

//Hash哈希表-两数之和
#include<bits/stdc++.h>
using namespace std;
int n, target;
int nums[10000];
unordered_map<int, int> ans_map;
int main(){
    cin >> n;
    for (int i = 0; i < n; i++){
        cin >> nums[i];
    }
    cin >> target;
    for (int i = 0; i < n; i++){
        unordered_map<int, int>::iterator it;
        it = ans_map.find(target - nums[i]);
        if (it != ans_map.end()){
            printf("%d %d\n", it->second, i);
        }
        else {
            ans_map.insert(pair<int, int>(nums[i], i));
        }
    }
    return 0;
}

总结

简而言之,哈希表就是一个容器,哈希法就是以空间换取时间的方式,可以大幅降低时间复杂度,从而提高程序的运行效率,哈希表结合了STL中的容器,在解题上技巧性很强,主要用于查询某个元素是否出现过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值