必学算法——哈希算法

前言

哈希算法是必须掌握的一种基础算法,在一些比较出名的竞赛acm、蓝桥杯,并且在一些公司面试题中都可能会出现,而且作为简单题我们必须要拿下,所以我们要引起重视,下面让我们来深入了解哈希算法。
在这里插入图片描述

一、什么是哈希算法

哈希算法,也称为散列算法,是一种数学函数或算法,它能够将任意长度的数据(称为“消息”)转换为固定长度的字符串(称为“哈希值”或简称“哈希”)。

二、哈希算法的原理

哈希算法的原理是将输入的数据按照一定的规则进行运算,从而得到一个固定长度的输出。具体来说,算法会将输入的数据分割成若干个等长或不等长的块,每个块称为一个消息块。然后,对每个消息块进行一系列的位运算、移位运算、模运算、异或运算等,从而得到一个中间结果,称为一个消息摘要。最后,将所有消息摘要进行组合或再次运算,从而得到最终的输出,即哈希值。

三、哈希算法的特点

1.高效性:计算速度快,能够快速生成哈希值。

2.唯一性:不同的输入数据生成的哈希值几乎不可能相同(尽管存在极小的碰撞概率)。

3.不可逆性:根据哈希值无法推导出原始输入数据,这是哈希算法的重要安全特性。

四、哈希算法的应用场景

1.数据安全:哈希算法可以用来验证数据的完整性和来源,例如数字签名、校验和、指纹等。通过比较数据经过哈希算法得到的哈希值是否相同,可以判断数据是否被篡改或伪造。

2.数据检索:哈希算法可以用来构建高效的数据结构,例如哈希表、布隆过滤器、默克尔树等。通过使用哈希值作为键或节点,可以实现快速的数据插入、删除和查找。

3.数据分片:在分布式系统中,哈希算法可以用于数据分片,以便将海量数据分布到多台机器上进行并行处理。

4.负载均衡:通过哈希算法,可以对客户端IP地址或会话ID计算哈希值,然后将取得的哈希值与服务器列表的大小进行取模运算,最终得到的值就是应该被路由到的服务器编号。这样可以实现会话粘滞的负载均衡策略。

5.分布式存储:在分布式存储系统中,哈希算法可以用于确定数据的存储位置。例如,通过哈希算法对数据取哈希值,然后对机器个数取模,得到的最终值就是应该存储的缓存机器编号。此外,一致性哈希算法还可以解决机器扩展时的数据迁移问题。

五、经典例题

1.字符统计

(帅哥这个蓝色字体可以点进去看原题)

代码题解

#include <iostream>
#include<string>
#include<unordered_map>
using namespace std;
int main()
{
    string s;
    cin >> s;
    int hash[256] = {0};//用于记录每个字母出现次数
    for(int i = 0; i < s.size(); i++){
        hash[s[i]]++;
    }
    int maxc = 0;
    char ret[256];//结果数组用于存储出现次数最多的字母
    int retSize = 0;//最长字母个数
    for(char c = 'A'; c <= 'Z'; c++){
        if(hash[c] > maxc){
            maxc = hash[c];
            retSize = 0;//如果发现更长的字母就把结果数组长度变为0,0下标的值变成新的最多字母
            ret[retSize++] = c;
        }
        else if(hash[c] == maxc){//如果发现最长字母的个数一样多就把这个字母插入结果数组
            ret[retSize++] = c;
        }
    }
    ret[retSize] = '\0'; //把这个结果数组变成字符串
    cout << ret << endl;
    return 0;
}

2.字符串统计

(帅哥这个蓝色字体可以点进去看原题)

代码题解

#include <iostream>
#include<string>
#include<unordered_map>
using namespace std;
int main()
{
  // 请在此输入您的代码
  unordered_map<string,int> m;
  int n;
  cin>>n;
  string s;
  for(int i=0;i<n;i++){
    cin>>s;
    m[s]=1;//给该键标记存在了
  }
  cout<<m.size()<<endl;
  return 0;
}

3.优质数对

(帅哥这个蓝色字体可以点进去看原题)

代码题解

#include <iostream>
#include<unordered_map>
using namespace std;
#define ll long long
#define sb 1000000001
int a[100001],b[100001];

int main()
{
  // 请在此输入您的代码
  int n;
  cin>>n;
  for(int i=0;i<n;i++)cin>>a[i];
  for(int i=0;i<n;i++)cin>>b[i];
  unordered_map<ll,int>h;
  ll ret=0;
  for(int j=0;j<n;j++){//a[i]=b[j] b[i]=a[j],优质数对的条件
    ll x=(ll)a[j]*sb+b[j];//哈希表的查找过程
    ret+=h[x];
    ll y=(ll)b[j]*sb+a[j];//哈希表的插入过程
    h[y]++;
  }
  
  cout<<ret<<endl;
  return 0;
}

六、结语

学习算法是一个很艰难,漫长的过程,我们要克服一切困难,学习算法本就是由易到难,我相信通过我们坚持不懈的努力一定能理解并熟练掌握其中细节,加油,我相信你一定能行。
在这里插入图片描述
关注我让我们一起学习编程,希望大家能点赞关注支持一下,让我有持续更新的动力,谢谢大家。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值