TimesIsMoney
Time Limit: 1000MS
Memory Limit: 65536KB
Problem Description
给你一个序列,有N个整数(int以内),判断一个数在这个序列中出现几次。
Input
多组输入,输入到文件结尾
首先输入一个n,然后输入n个整数。
在输入一个m,代表查询的个数 ,然后输入m个数(int以内)。
n,m <= 100000;
Output
对应每一次查询,输出这个数在序列中出现几次。
Example Input
5 1 2 2 3 5 3 2 4 5
Example Output
2 0 1
解题思路:一看到题目就想到用哈希表,最原本的思路是直接利用输入的数作为下标来存储数组,
int a[110000],ha[110000];
memset(ha,0,sizeof (ha));
for (int i=0;i<n;i++)
{
scanf ("%d",&a[i]);
ha[a[i]] = a[i];
}
可是把这道题想的太过简单了,输入的N个数是整数int范围之内的,(至少是10的9次方),
而N的范围只有100000大小,因此一定会出现TLE,在N遍TLE的提交后,才想到利用链地址
的方法,(F(key) = key%p),p选择了20 之内的质数19;链表头指针数组的大小也要按照p的大
小做选择,否则会出现MLE。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int a[110000];
struct node
{
int data;
int num;//利用num计数,重复的元素不再插入,直接将指针指向的num++
struct node *next;
};
struct node *ha[100];
int main()
{
int n,m,key;
int i,j;
while (~scanf ("%d",&n))
{
for (i=0; i<100; i++)//根据P的大小开内存
{
ha[i] = (struct node *)malloc (sizeof (struct node));
ha[i]->next = NULL;
}
for (i=0; i<n; i++)
{
scanf ("%d",&a[i]);
int t = a[i]%19;
struct node *p = (struct node *)malloc (sizeof (struct node));
p->data = a[i];
struct node *q = ha[t];
while (q->next!=NULL)//链表的数据域按从大到小的顺序建立(直接插入法)
{
if (p->data < q->next->data)
{
p->next = q->next;
q->next = p;
p->num=1;
break;
}
if (p->data == q->next->data)
{
q->next->num++;
break;
}
q = q->next;
}
if (q->next == NULL)
{
q->next = p;
p->next = NULL;
p->num=1;
}
}
scanf ("%d",&m);
for (i=0; i<m; i++)
{
int f = 0;
scanf ("%d",&key);
int t = key%19;
struct node *q = ha[t]->next;
while (q!=NULL)
{
if (q->data==key)
{
f = 1;
printf ("%d\n",q->num);
break;
}
q = q->next;
}
if (f==0)
printf ("0\n");
}
}
return 0;
}