哈希表(知识点+leetcode)以及字符串哈希

一、什么是哈希表

哈希表是散列表,就是通过关键码值而直接进行访问的一种数据结构

哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素

其内部由一个个key:value 样式的键值对组成。

哈希表中的key通过哈希函数得到内存地址,然后将key和value放到对应的内存地址,从而实现通过key获取Value的方式

哈希碰撞:2个不同的key通过哈希函数(hash function)得到了相同的内存地址,也就是是内存地址已经被一个占用了,解决方法是将其中之一变为链表结构,使用next指向。这样内存地址就不会重复,但是会影响查询

二、哈希表常见结构介绍

总体结构上分为数组、set、map

  • 数组也是一种意义上的哈希表
  • set的结构中每个元素都是一个值(类似于数组)
  • map的结构是一个 key:value 的数据结构

重点讲:unordered_map(哈希表)

  • unordered_map底层存储的是<key,value>键值对,可以通过key快速的索引到value unordered_map内部因为是数据是通过映射存入哈希桶内的,所以对unordered_map进行遍历得到的是一个无序的序列
  • unordered_map通过key进行访问的速度比map快,但是遍历元素的迭代效率就要低于map了。unordered_map也实现了operator[ ] 可以通过key直接访问到value

以上概念来源于:https://blog.csdn.net/qq_60831089/article/details/131465770?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522172111625416800213021917%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=172111625416800213021917&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-2-131465770-null-null.142^v100^pc_search_result_base5&utm_term=哈希表c%2B%2B&spm=1018.2226.3001.4187

leetcode经典例题

242 有效的字母异位词

题目来源:https://leetcode.cn/problems/valid-anagram/description/

思路

使用哈希表下标索引,判断这两个字符串每个字符出现的次数即可。

编程

class Solution {
public:
    bool isAnagram(string s, string t) {
          int hash[27]={0};
          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) return false;
          }
          return true;
    }
};

349 两个数组的交集

题目来源:https://leetcode.cn/problems/intersection-of-two-arrays/description/

思路

选择unordered_set避免数据重复,将nums1的序列存入哈希表unordered_set中,遍历查找nums2相同的值即可

编程

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
      unordered_set<int> ans;
      unordered_set<int> a(nums1.begin(),nums1.end());
      for(int i=0;i<nums2.size();++i){
        if(a.find(nums2[i])!=a.end()){
            ans.insert(nums2[i]);
        }
      }
      return vector<int>(ans.begin(),ans.end());    
    }
};

1 两数之和

思路

选择unordered_map来存储数值和下标,遍历nums数列,若在unordered_map找到target-nums[i]对应的值,则输出它们的下标,找不到则将当前的值和下标存入哈希表即可

编程

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> ans;
        for(int i =0;i<nums.size();i++){
            auto t= ans.find(target-nums[i]);
            if(t==ans.end()){
                ans.insert(make_pair(nums[i],i));
            }
            else{
                return {t->second,i};
            }
        }
        return {};
    }
};

454 四数相加II

思路

先对式子做移项处理,nums1[i] + nums2[j] =-(nums3[k] + nums4[l] ),那么我们也是选择用unordered_map来存储数组,先将nums1[i] + nums2[j] 的所有数存入哈希表中,然后在哈希表里面找-(nums3[k] + nums4[l] ),若匹配则计数器加上哈希表-(nums3[k] + nums4[l] )的个数,最后返回计数器即可

编程

class Solution {
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
         unordered_map<int,int> m;
         int ans=0;
         for(auto i : nums1)
            for(auto j : nums2){
                m[i+j]++;
            }
        for(auto i : nums3)
           for(auto j : nums4){
            int t=-(i+j);
            if(m.find(t)!=m.end()) ans+=m[t];
           }
        return ans;
    }
};

字符串哈希

题目来源:https://www.luogu.com.cn/problem/P3370

前言

字符串哈希是一种将字符串映射为整数的算法。哈希函数将字符串映射到一个固定大小的整数,这个整数通常称为哈希值或哈希码。

思路

首先防止数据溢出,我们需要用到unsigned long long(当数据超出264时会自动取模),参数p取131防止哈希碰撞,对于这题来说用的是进制哈希(把每个字符看作每个进制位上的一个数字,这个串转换为一个基于进制p的数),将字符串通过进制哈希转换完后进行排序,最后比较相邻元素即可

编程

const int N=1e4+5;
ULL a[N],p=131,h=0;
void solve(){
	int n;cin >> n;
	for(int i=0;i<n;++i){
		string s;cin >> s;
		h=0;
		for(int i=0;i<s.size();++i){
			h=h*p+s[i];
		}
		a[i]=h;
	}
	int ans=0;
	sort(a,a+n);
	for(int i=0;i<n;++i){
		if(a[i]!=a[i+1]) ans++;
	}
	cout << ans;
	return ;
}
  • 41
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值