数据结构之哈希表

数据结构实验:哈希表

Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^

题目描述

在n个数中,找出出现次数最多那个数字,并且输出出现的次数。如果有多个结果,输出数字最小的那一个。

输入

单组数据,第一行数字n(1<=n<=100000)。
接下来有n个数字,每个数字不超过100000000

输出

出现次数最多的数字和次数。

示例输入

3
1 1 2

示例输出

1 2

 

首先声明本渣还没学会哈希,这篇就当哈希的预习篇吧 写的不好大家见谅

首先说一下我最初的思路,因为要统计出现次数,所以第一反应是对于每一个数字对应一个键值,我们建这么一个数组 h[10000000] 比如对于输入这么一串数字1 2 2 4 9 其中1对应h[1] 2对应h[2] 4对应h[4] 总结一下就是i 对应 h[i], 每扫到一个数字i ,h[i]++,那么最终就会统计完所有数字出现的数字  but,当我提交了之后意料之中的没有过,怎么回事?超内存了,是的我们可以看到每一个数字的范围是在一亿以内,就意味着我们需要声明一个一亿大小的h[],但实际上只有10000个数字,会有大量的空间用不到,怎么办呢?书上说可以对一个大的素数取余,但那样的话就会产生冲突了,不难想象吧,比如还是上面那串数字,假设h[]大小为5(对5取余),那么数字4 和数字9都会对应同一个键值 h[4]

怎么办?书上说要将hash表的每一个位置做成一个链表(原谅我 我没看懂,暑假我要好好学数据结构!)难道就不能做了吗,网上看到某大牛的解法(大牛好像都不爱写解题报告,意识流选手orz),看了半天终于算是看出点道道来了 在说之前,先讲两个函数(STL模板里面的)我也是现学的,一个是upper_bound(a,a+n,a[i]) 他返回容器里面第一个大于a[i]的元素的下标,另一个是lower_bound(a,a+n,a[i]) 返回容器里面第一个大于等于a[i]的元素的下标 还是看上面的那串数字(已sort) 1 2 2 4 9 upper 返回值依次是1 3 3 4 5(注意最后一个,数组会越界) lower的返回值依次是0 1 1 3 4 然后另upper-lower 得到 1 2 2 1 1 仔细观察 他们是不是正是对应位置数字出现的次数?这算不算也是一种哈希?这样 有多少个数字我们就可以只声明多大的数组就可以了。

 

 神级写法

#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
	int a[100001],hash[100001],i,n,max;
	scanf("%d",&n);
	for(i=0;i<n;i++)
	scanf("%d",&a[i]);
	sort(a,a+n);
	for(i=0;i<n;i++)
	hash[i]=upper_bound(a,a+n,a[i])-lower_bound(a,a+n,a[i]); 
	max=0;
	for(i=1;i<n;i++)
	if(hash[max]<hash[i])max=i;
	printf("%d %d\n",a[max],hash[max]);
}


下面用map 做了一个
#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <string>
#include <map>
using  namespace std;
int main()
{
  map <int,int> m;
  map <int,int>::iterator i,max;
  int n,x;
  cin>>n;
  while(n--)
  {
  	cin>>x;
  	++m[x];
  }
  max=m.begin();
  i=m.begin();
  while(i!=m.end())
  {
  	if(i->second>max->second)
		max=i;
	i++;
  }
  cout<<max->first<<" "<<max->second<<endl;
  return 0;
}

在来一个链地址法

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <cctype>
#include <algorithm>
using namespace std;
const int MOD=100000;
typedef struct node
{
    int num;
    int time;
    node *next;
}*N,Hash;
Hash a[100010];
int main()
{
    ios::sync_with_stdio(false);
    int n,x;
    cin>>n;
    N p,q;
    while(n--)
    {
        cin>>x;
        int tem=x%MOD;
        p=&a[tem];q=p;
        int flag=1;
        while(p!=NULL)
        {
            if(p->num==x)
            {
                p->time++;
                flag=0;
                break;
            }
            q=p;
            p=p->next;
        }
        if(flag)
        {
            p=new Hash;
            p->num=x;
            p->time=1;
            p->next=NULL;
            q->next=p;
        }
    }
        int Num,Max_time=0;
        for(int i=0;i<MOD;i++)
        {
            p=a[i].next;
            while(p!=NULL)
            {
                if(p->time>Max_time)
                {
                    Num=p->num;
                    Max_time=p->time;
                }
                else if(p->time==Max_time)
                {
                    Num=p->num<Num?p->num:Num;
                }
                p=p->next;
            }
        }
    cout<<Num<<" "<<Max_time<<endl;
    return 0;
}


 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值