POJ3349总结(第一次用hash解决问题)

POJ3349(第一次用hash解决问题)

解题思路

1.题目意思比较简单,就是给出一组雪花的数据,然后判断这组雪花里边有没有相同的雪花。也就是判断是否存在两个数组,其所有元素都相同。

2.1暴力破解的思路当然很简单了,每输入一个雪花数据,都将其与已输入数据进行比较;如果存在有相等的,那么就输出“twin snowflakes fount”;否则就继续输入。

2.2第二步中的比较过程则是将两个数组排序后比较对应位。

3.上述思路的代码交上去是time limit exceeded。

4.1这个题目利用hash则会大大提高效率

4.2首先计算一个雪花的hash值,然后将这个雪花放在hash链表的相应位置。如果之前已有相同hash值得雪花存在,那么再把当前雪花与所有已存在的同hash值雪花进行比较。如果没有相同hash值雪花,则说明目前没有与该雪花信息相同的。

4.3上述的hash函数是自定义的,主要目的是将大量的雪花先分堆,然后再进行比较。(因为大量的排序和比较是很耗费时间的,所以hash函数的计算最好是简单却又能将数据分开的)

注意点

1.结构体的定义中。如果当前结构体内部的变量有该结构体类型的指针、或引用了其他结构体,那么被引用的内容需要提前定义或声明。

2.在比较过程中会使用到链表,这里一定要注意逻辑明晰。如下代码,写错的话有可能会出现当前结点最后会和自己进行比较等问题。

    while(p!=NULL)
    {
        //printf("%d%d%d%d%d%d\n",p->info[0],p->info[1],p->info[2],p->info[3],p->info[4],p->info[5]);
        for(i=0;i<6;i++)
        {
            if(p->info[i]!=a->info[i])
            {
                break;
            }
        }
        if(i==6)
        {
            return true;
        }
        pre=p;
        p=p->next;
    }
    pre->next=a;

3.hash计算的时候,取模后计算再取模比较好。防止计算后数过大产生溢出。

int toHash(p_Flake a)
{
    int sum=0;
    for(int i=0;i<6;i++)
    {
        sum+=(a->info[i])%100000;
    }
    return sum%100000;
}

代码

#include<stdio.h>
#include<stdlib.h>

typedef struct SnowFlake{
    int info[6];
    SnowFlake* next;
}*p_Flake;

#define max 100000

p_Flake hashArray[100000]={NULL};

int toHash(p_Flake a);
bool insertToHash(p_Flake a, int aHash);
void sort(p_Flake a);

int main()
{
    int N=0;
    scanf("%d",&N);
    int flag=0;
    for(int k=0;k<N;k++)
    {
        p_Flake a=NULL;
        a=(p_Flake)malloc(sizeof(SnowFlake));
        a->next=NULL;
        scanf("%d%d%d%d%d%d",a->info,a->info+1,a->info+2,a->info+3,a->info+4,a->info+5);

        if(flag==0)
        {
            if(insertToHash(a,toHash(a))==true)
            {
                flag=1;
            }
        }
    }
    if(flag==1)
    {
        printf("Twin snowflakes found.\n");
    }
    else
    {
        printf("No two snowflakes are alike.\n");
    }
    return 0;
}

void sort(p_Flake a)
{
    for(int i=0;i<6;i++)
    {
        for(int j=0;j<6-i-1;j++)
        {
            if(a->info[j+1]<a->info[j])
            {
                int swap=a->info[j+1];
                a->info[j+1]=a->info[j];
                a->info[j]=swap;
            }
        }
    }
}

bool insertToHash(p_Flake a, int aHash)
{
    int i=0;
    sort(a);
    if(hashArray[aHash]==NULL)
    {
        hashArray[aHash]=a;
        return false;
    }


    p_Flake pre=NULL;
    p_Flake p=hashArray[aHash]; 
    while(p!=NULL)
    {
        for(i=0;i<6;i++)
        {
            if(p->info[i]!=a->info[i])
            {
                break;
            }
        }
        if(i==6)
        {
            return true;
        }
        pre=p;
        p=p->next;
    }
    pre->next=a;
    return false;
}

int toHash(p_Flake a)
{
    int sum=0;
    for(int i=0;i<6;i++)
    {
        sum+=(a->info[i])%100000;
    }
    return sum%100000;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值