问题分析
在n (n<100000)个雪花中判断是否存在两片完全相同的雪花,每片雪花有6个角,每个角的长度限制为1000000
雪花相等的条件为, 雪花6个角的长度按顺序相等(这个顺序即可以是顺时针的也可以是逆时针的)
在n个雪花中,查找两片是否相等的雪花,采用暴力解法其,各个元素逐个比较的话,则其时间复杂度为n的平方,由于n可能会很大提交时肯定超时,所以选择采用哈希方法来查找两个判断两个元素是否相等,
算法流程:
1 建立一个雪花的节点node,并且获取其6个角的长度,当拥有相同的hash值的雪花时,即产生冲突时,采用开放地址发,即用链表存放拥有相同哈希值的雪花节点,该链表的头节点存放在哈希数组中
2 判断拥有哈希值的雪花是否相等。
代码
/*
poj 3349
哈希算法
用G++编译提交通过,但用C++编译提交时会超时
*/
#include < iostream >
#include < algorithm >
#include < cstdio >
const long maxn = 100000 ;
const long mtemp = 100000 ;
/*
每片雪花的具体长度,并且是一个链表
*/
typedef struct node
{
long data[ 6 ];
node * next;
}node;
/*
存放雪花的初始地址
*/
typedef struct hnode
{
int elCount;
node * head;
}HeadNode;
/*
全局变量
*/
HeadNode * snows = new HeadNode[maxn];
/*
比较两片雪花是否相等
*/
bool CompareArray( long * d1, long * d2, const long len)
{
int i,j,count,t;
bool flag = false ;
count = 0 ;
/*
从数组的头开始判断两个数组是否相等,即两片雪花是否相等
依次以d1数组的第 i(0<=i>=5)个元素作为头依次和d2数组的元素作比较,
只有各个元素都相等时才证明两片雪花相等。
*/
while (count < len)
{
i = count;
for (j = 0 ;j < len;j ++ )
{
if (d1[i] == d2[j])
{
i ++ ;
if (i >= len)i = 0 ;
} else
{
break ;
}
}
if (j >= len)
{
flag = true ;
}
if (flag == true ) break ;
count ++ ;
}
/*
从数组的末尾开始判断两个数组是否相等
*/
if (flag == false )
{
count = len - 1 ;
while (count >= 0 )
{
i = count;
for (j = 0 ;j < len;j ++ )
{
if (d1[i] == d2[j])
{
i -- ;
if (i < 0 )i = len - 1 ;
} else
{
break ;
}
}
if (j >= len)
{
flag = true ;
}
if (flag == true ) break ;
count -- ;
}
}
return flag;
}
int main( void )
{
long n,c,k,key,index;
int i,j;
long * a;
bool isHasSameSnowFlake;
node * t, * headtemp;
std::cin >> n;
c = getchar();
isHasSameSnowFlake = false ;
for (i = 0 ;i < n;i ++ )
{
// a=new long[6];
t = new node();
t -> next = NULL;
key = 0 ;
for (j = 0 ;j < 6 ;j ++ )
{
k = 0 ;
c = ' 0 ' ;
while (c != ' \n ' && c != ' ' )
{
k = k * 10 + c - ' 0 ' ;
c = getchar();
}
t -> data[j] = k;
key += k;
}
// qsort(a,6,sizeof(long),Compare);
if (isHasSameSnowFlake == false )
{
index = key % mtemp; // 取当前输入的雪花的hash值,通过求6个角的长度的和,然后对mtemp相除取余数,即为其hash值
if (snows[index].elCount > 0 ) // 判断已经输入的雪花中是否已经存在拥有相同hash值的雪花
{
headtemp = snows[index].head -> next;
while (headtemp != NULL)
{ // 判断拥有相同hash值的雪花是否是两片相同的雪花
isHasSameSnowFlake = CompareArray(headtemp -> data,t -> data, 6 );
if (isHasSameSnowFlake == true ) break ;
headtemp = headtemp -> next;
}
if (isHasSameSnowFlake == false )
{
t -> next = snows[index].head -> next;
snows[index].head -> next = t;
snows[index].elCount ++ ;
}
/* t->next=snows[index].head->next;
snows[index].head->next=t; */
} else
{
snows[index].elCount ++ ;
snows[index].head = new node();
snows[index].head -> next = t;
}
}
}
if (isHasSameSnowFlake == false ){
std::cout << " No two snowflakes are alike. " << std::endl;
} else {
std::cout << " Twin snowflakes found. " << std::endl;
}
return 0 ;
}
poj 3349
哈希算法
用G++编译提交通过,但用C++编译提交时会超时
*/
#include < iostream >
#include < algorithm >
#include < cstdio >
const long maxn = 100000 ;
const long mtemp = 100000 ;
/*
每片雪花的具体长度,并且是一个链表
*/
typedef struct node
{
long data[ 6 ];
node * next;
}node;
/*
存放雪花的初始地址
*/
typedef struct hnode
{
int elCount;
node * head;
}HeadNode;
/*
全局变量
*/
HeadNode * snows = new HeadNode[maxn];
/*
比较两片雪花是否相等
*/
bool CompareArray( long * d1, long * d2, const long len)
{
int i,j,count,t;
bool flag = false ;
count = 0 ;
/*
从数组的头开始判断两个数组是否相等,即两片雪花是否相等
依次以d1数组的第 i(0<=i>=5)个元素作为头依次和d2数组的元素作比较,
只有各个元素都相等时才证明两片雪花相等。
*/
while (count < len)
{
i = count;
for (j = 0 ;j < len;j ++ )
{
if (d1[i] == d2[j])
{
i ++ ;
if (i >= len)i = 0 ;
} else
{
break ;
}
}
if (j >= len)
{
flag = true ;
}
if (flag == true ) break ;
count ++ ;
}
/*
从数组的末尾开始判断两个数组是否相等
*/
if (flag == false )
{
count = len - 1 ;
while (count >= 0 )
{
i = count;
for (j = 0 ;j < len;j ++ )
{
if (d1[i] == d2[j])
{
i -- ;
if (i < 0 )i = len - 1 ;
} else
{
break ;
}
}
if (j >= len)
{
flag = true ;
}
if (flag == true ) break ;
count -- ;
}
}
return flag;
}
int main( void )
{
long n,c,k,key,index;
int i,j;
long * a;
bool isHasSameSnowFlake;
node * t, * headtemp;
std::cin >> n;
c = getchar();
isHasSameSnowFlake = false ;
for (i = 0 ;i < n;i ++ )
{
// a=new long[6];
t = new node();
t -> next = NULL;
key = 0 ;
for (j = 0 ;j < 6 ;j ++ )
{
k = 0 ;
c = ' 0 ' ;
while (c != ' \n ' && c != ' ' )
{
k = k * 10 + c - ' 0 ' ;
c = getchar();
}
t -> data[j] = k;
key += k;
}
// qsort(a,6,sizeof(long),Compare);
if (isHasSameSnowFlake == false )
{
index = key % mtemp; // 取当前输入的雪花的hash值,通过求6个角的长度的和,然后对mtemp相除取余数,即为其hash值
if (snows[index].elCount > 0 ) // 判断已经输入的雪花中是否已经存在拥有相同hash值的雪花
{
headtemp = snows[index].head -> next;
while (headtemp != NULL)
{ // 判断拥有相同hash值的雪花是否是两片相同的雪花
isHasSameSnowFlake = CompareArray(headtemp -> data,t -> data, 6 );
if (isHasSameSnowFlake == true ) break ;
headtemp = headtemp -> next;
}
if (isHasSameSnowFlake == false )
{
t -> next = snows[index].head -> next;
snows[index].head -> next = t;
snows[index].elCount ++ ;
}
/* t->next=snows[index].head->next;
snows[index].head->next=t; */
} else
{
snows[index].elCount ++ ;
snows[index].head = new node();
snows[index].head -> next = t;
}
}
}
if (isHasSameSnowFlake == false ){
std::cout << " No two snowflakes are alike. " << std::endl;
} else {
std::cout << " Twin snowflakes found. " << std::endl;
}
return 0 ;
}