1102 A-B数对

1102 A-B数对

这道题我早就做过了,但是因为今天研究了hash所以必须得来复习复习
我们得先明白题意,就是说输入n c 然后输入n个数枚举ab,是使得a-b=c

O(n^2)思路

这种思路是暴力进行枚举,朴素算法二重循环,这样做肯定会超时,这个题肯定没有这么简单的

O(nlogn)思路

利用二分思想一次循环枚举b,中间二分找c然后再相加判断a就好了

O(n)思路

优化一点的算法,就是用桶保存每一个数,这样的话我们只需要枚举b,然后判断一下c是不是存在就好了,这样时间复杂度会很低,但同时空间复杂度会很高,就会MLE

hash

hash才是我们的正解,才是我们应该做的,是这些解法里面最优秀的,那么怎么进行实现呢。
我们前面谈桶的时候,代价是用空间换时间,空间代价非常的高,hash就避免了这一点。
其实我们可以发现,桶数组很多桶会空,也就是说浪费空间了,比如四个数 2 4 7 10001,如果用桶的话我们就得开10001但是用hash只需要4个
2%4=2 4%4=0 7%4=3 10001%4=1
其实存hash的就是%一个数而已,但是%的过程中这个位置如果有数,那么就放后面,这就是取余法和再hash法
还有我们取余的数通常就是一个质数,1000003
1.输入然后映射散列表
2.映射过程中进行解决冲突
3.统计查找,也就是调用散列表
---------------重新-----------
最简单的做法就是暴力
当然暴力 肯定不是正解
还有一些二分了 桶了的
经过一些沉淀什么的,hash是这个题的正解
hash是一个函数,是一种映射,他表示的是一种关系的对应
他解决了桶的代价,有很多无用的空桶,我们需要将这些桶处理,因为他们太占空间,这就是唯一的缺点

hash的对应关系%一个数而已,但是%的过程中这个位置如果有数,那么就放后面,这就是取余法和再hash法
步骤就是三个

1.输入然后映射,预处理
2.解决冲突,也就是hash重复的函数值
3.统计查找,根据题目进行寻找

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define p 1000003//这就是我们需要取余的数
#define hash(a) a%p//hash函数 
using namespace std;
long long n,m,a[p],ans;
struct node{
	long long x;//这个位置对应的数 
	int y;//次数 
}h[p];
int findd(long long x)
{//hash关键字,避免冲突的 
	int y=hash(abs(x));//获取hash值 
	while(h[y].x&&h[y].x!=x) y=hash(++y);
	//避免冲突,往一个存 
	return y; 
}
void push(long long x)
{//映射散列表 
	int y=findd(x);
	h[y].y++;
	h[y].x=x;
	//存储再散列表中然后次数加一 
 }
 int check(long long x)
 {//统计次数 
 	return h[findd(x)].y;
 }
int main()
{
	cin>>n>>m;
	for(long long i=1;i<=n;i++)
		cin>>a[i],push(a[i]);
	for(long long i=1;i<=n;i++)
		ans+=check(a[i]-m);//统计出现次数 
	cout<<ans<<endl;
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值