算法与数据结构第七次作业 太阳帝国



继续hash,这题我自己也AC了,不过当时没用hash,先说一下我自己的思路。然后再贴大神的hash。

这题显然是求交集的问题。

我首先把第一个集合作为当前的交集。然后每进来一组集合,就和当前交集求一次交集。自己实现了一个求交集的函数,就是排序后,用两个游标非别指两个集合,遇到一样的就取出存到另一个集合中去。最后在把这个集合赋值给当前集合。

显然还有一个去重的问题。在输出的时候,遇到一样的就不输出。

贴代码:

 
            #include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

bool cmp(int a,int b)
{
	return a<b;
}

int ans[1001]={-1};

int intersection(int tmp[],int m1,int ans[],int m2)
{
	int point1=0,point2=0,i=0,j,c[1001]={-1};
	if(tmp==NULL||ans==NULL||m1==0||m2==0)
		return -1;
	else
	{
		while(point1<m1&&point2<m2)
		{
			if(tmp[point1]>ans[point2])
			{
				point2++;
			}
			else if(tmp[point1]==ans[point2])
			{
				c[i++]=tmp[point1];
				point1++;
				point2++;
			}
			else
				point1++;
		}
	}
	if(i==0)return -1;
	else
	{
		for(j=0;j<i;j++)
			ans[j]=c[j];
		return i;
	}
}

int main()
{
	int n,m1,m2,i,j,count,t=0;
	int tmp[1001]={-1};
	scanf("%d",&n);
	scanf("%d",&m2);
	for(i=0;i<m2;i++)
	{
		scanf("%d",&ans[i]);
	}
	sort(ans,ans+m2,cmp);
	for(i=0;i<n-1;i++)
	{
		scanf("%d",&m1);
		for(j=0;j<m1;j++)
		{
			scanf("%d",&tmp[j]);
		}
		sort(tmp,tmp+m1,cmp);
		count=intersection(tmp,m1,ans,m2);
		m2=count;
		if(count==-1)
		{
			break;
		}
	}
	if(i>=n-1||n==1)
	{
		for(j=1;j<m2;j++)
		{
			if(ans[j]==ans[j-1])continue;
			else
				t++;
		}
		printf("%d\n%d",t+1,ans[0]);
		for(j=1;j<m2;j++)
		{
			if(ans[j]==ans[j-1])continue;
			else
				printf(" %d",ans[j]);
		}
		printf("\n");
	}
	else
		printf("0\n");
	return 0;
}

/*
4
2 2 4
2 2 4
3 2 2 4 
4 2 3 4 5
*/
		



        


接下来讲hash,这次参考了另外一个大神的代码,看懂了,也学到了解决冲突的方式,邹大神的代码真心难懂。

#include <iostream>
#include <cstdio>
#include <algorithm>
#define LL __int64
#define N 100003
#define MOD 100003//模值
using namespace std;
int cnt[N],has[N];//cnt用于计数,计每个元素是否在每个集合都出现过
bool vis[N];
int ans[1007];

inline int hash(int x){
	int y=(x%MOD+MOD)%MOD;
	while(vis[y]&&has[y]!=x)//解决冲突,采用线性重新散列技术
		y=(y+1)%MOD;
	return y;
}

int main(){
	int n,m;
	scanf("%d",&n);
	memset(cnt,0,sizeof(cnt));
	memset(vis,false,sizeof(vis));
	int x,y;
	for(int i=1;i<=n;i++){
		scanf("%d",&m);
		for(int j=0;j<m;j++){
			scanf("%d",&x);
			y=hash(x);
			if(cnt[y]==i-1){//这里本来在疑惑重复的问题,后来发现,是与i相关而不是j
				cnt[y]++;
				has[y]=x;
				vis[y]=true;
			}
		}
	}
	int tot=0;
	for(int k=0;k<MOD;k++){
		if(cnt[k]==n)
			ans[tot++]=has[k];
	}
	sort(ans,ans+tot);
	printf("%d\n",tot);
	for(int r=0;r<tot;r++){//这个末尾无空格的方式和我以往用的不同,学习
		printf("%d",ans[r]);
		if(r==tot-1)
			printf("\n");
		else
			printf(" ");
	}
	return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值