QuickSort和Hash Table在Sum题目中的应用.
2005-04-11 01:20
337 查看
今天遇到了一道难题.题目如下:
Sum
Mr. Jojer is given n numbers and an extra integer x, he wants to know whether there are two numbers whose sum is x.
Input
The input file contains several test cases. The first line of each test case contains two integers, n(<=1000001) and x. From the next line of each test case, there are n numbers.
Output
Each test case corresponds to a line in the output, which is either "YES" if there exists an answer or "NO" if not.
Sample Input
3 3
1 2 3
2 3
1 3
Sample Output
YES
NO
Submit your solution从题目的限制条件可以看出,要求要在1000001多个整数中查找两个其和为X的整数,其计算量是十分巨大的.而题目要求的是30秒中完成一批数目的测试(几组).如果采用一般的循环2阶相加比较,是现在完不成的.我这里有两套解决办法.1.以内存换速度.
在为了提高运行速度的问题上,首先就应该想到的是以空间代价换取时间上的代价.最能体现这点的就是我们数据结构中所学习的Hash表.Hash表查找速度十分快,可能我们这里如何把Hash表应用进来呢?我采用了比较笨的办法.
循环每组数中的每个元素,首先检查其值是否存在Hash表中,如果存在,说明"YES"。否则将其 X - 元素 的值插入一个Hash表。那么这样下去,我只需要一个1阶的算法就能完成。不过这个Hash表十分巨大。不过,我们只需要把在一般范围内的整数放进Hash表记录,如果数值的范围超过了Hash能表示的范围,就单独出来存放在一个线性表中。
下面是我已经调试通过,并且在ACM Online Judge上Accpeted的源程序。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>#define MAX_N 3000002
long integers[MAX_N];char regularTab[MAX_N];
long extendTab[MAX_N];
long numExt;long n;
long x;
void insertTab(int a);
int lookup(int a);int main()
{
long i,j;
long m;
int Yes;
while(scanf("%ld%ld",&n,&x) == 2)
{
memset(regularTab,0,MAX_N);
memset(extendTab,0,MAX_N*sizeof(long));
numExt = 0;
Yes = 0; for(i=0; i<n; i++)
{
scanf("%ld",&integers);
} for(i=0;i<n;i++)
{
if(lookup(integers[i]))
{
printf("YES/n");
i = n;
Yes = 1;
break;
}
else
{
insertTab(x-integers[i]);
}
}
if(Yes == 0)
printf("NO/n");
} return 1;
}void insertTab(int a)
{
if(a > -MAX_N/2 && a < MAX_N/2)
{
regularTab[a+MAX_N/2] = 1;
}
else
{
extendTab[numExt++] = a;
}
}int lookup(int a)
{
if(a > -MAX_N/2 && a < MAX_N/2)
{
return regularTab[a+MAX_N/2];
}
else
{
long i;
for(i=0;i<numExt; i++)
{
if(extendTab[i] == a)
return 1;
}
return 0;
}
}
2.使用QuickSort和qsort函数
快速排序的算法不用在这里多讲了。在C语言的stdlib.h中已经提供了一个汇编级别的qsort函数。这道题目使用快速排序的办法就是让所有的数列先排序,然后再进行查找。虽然排序也是二阶算法,但是由于QuickSort的特殊性,使得排序的过程还是比较快,一旦排序完成后,根据X进行二分查找,几步就可以完成了。具体的实现程序我这里没有。不过我觉得qsort的函数使用是十分重要的,所以我从msdn上抄袭了qsort函数的示例代码。
void qsort(
void *[i]base,
size_t num,
size_t width,
int (__cdecl *compare )(const void *, const void *)
);
Sum
Time limit: | 30 Seconds | Memory limit: | 32768K Bytes | |
Submitted: | 375 | Accepted: | 44 |
Mr. Jojer is given n numbers and an extra integer x, he wants to know whether there are two numbers whose sum is x.
Input
The input file contains several test cases. The first line of each test case contains two integers, n(<=1000001) and x. From the next line of each test case, there are n numbers.
Output
Each test case corresponds to a line in the output, which is either "YES" if there exists an answer or "NO" if not.
Sample Input
3 3
1 2 3
2 3
1 3
Sample Output
YES
NO
Submit your solution从题目的限制条件可以看出,要求要在1000001多个整数中查找两个其和为X的整数,其计算量是十分巨大的.而题目要求的是30秒中完成一批数目的测试(几组).如果采用一般的循环2阶相加比较,是现在完不成的.我这里有两套解决办法.1.以内存换速度.
在为了提高运行速度的问题上,首先就应该想到的是以空间代价换取时间上的代价.最能体现这点的就是我们数据结构中所学习的Hash表.Hash表查找速度十分快,可能我们这里如何把Hash表应用进来呢?我采用了比较笨的办法.
循环每组数中的每个元素,首先检查其值是否存在Hash表中,如果存在,说明"YES"。否则将其 X - 元素 的值插入一个Hash表。那么这样下去,我只需要一个1阶的算法就能完成。不过这个Hash表十分巨大。不过,我们只需要把在一般范围内的整数放进Hash表记录,如果数值的范围超过了Hash能表示的范围,就单独出来存放在一个线性表中。
下面是我已经调试通过,并且在ACM Online Judge上Accpeted的源程序。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>#define MAX_N 3000002
long integers[MAX_N];char regularTab[MAX_N];
long extendTab[MAX_N];
long numExt;long n;
long x;
void insertTab(int a);
int lookup(int a);int main()
{
long i,j;
long m;
int Yes;
while(scanf("%ld%ld",&n,&x) == 2)
{
memset(regularTab,0,MAX_N);
memset(extendTab,0,MAX_N*sizeof(long));
numExt = 0;
Yes = 0; for(i=0; i<n; i++)
{
scanf("%ld",&integers);
} for(i=0;i<n;i++)
{
if(lookup(integers[i]))
{
printf("YES/n");
i = n;
Yes = 1;
break;
}
else
{
insertTab(x-integers[i]);
}
}
if(Yes == 0)
printf("NO/n");
} return 1;
}void insertTab(int a)
{
if(a > -MAX_N/2 && a < MAX_N/2)
{
regularTab[a+MAX_N/2] = 1;
}
else
{
extendTab[numExt++] = a;
}
}int lookup(int a)
{
if(a > -MAX_N/2 && a < MAX_N/2)
{
return regularTab[a+MAX_N/2];
}
else
{
long i;
for(i=0;i<numExt; i++)
{
if(extendTab[i] == a)
return 1;
}
return 0;
}
}
2.使用QuickSort和qsort函数
快速排序的算法不用在这里多讲了。在C语言的stdlib.h中已经提供了一个汇编级别的qsort函数。这道题目使用快速排序的办法就是让所有的数列先排序,然后再进行查找。虽然排序也是二阶算法,但是由于QuickSort的特殊性,使得排序的过程还是比较快,一旦排序完成后,根据X进行二分查找,几步就可以完成了。具体的实现程序我这里没有。不过我觉得qsort的函数使用是十分重要的,所以我从msdn上抄袭了qsort函数的示例代码。
void qsort(
void *[i]base,
size_t num,
size_t width,
int (__cdecl *compare )(const void *, const void *)
);
Example
// crt_qsort.c // arguments: every good boy deserves favor /* This program reads the command-line * parameters and uses qsort to sort them. It * then displays the sorted arguments. */ #include <stdlib.h> #include <string.h> #include <stdio.h> int compare( const void *arg1, const void *arg2 ); int main( int argc, char **argv ) { int i; /* Eliminate argv[0] from sort: */ argv++; argc--; /* Sort remaining args using Quicksort algorithm: */ qsort( (void *)argv, (size_t)argc, sizeof( char * ), compare ); /* Output sorted list: */ for( i = 0; i < argc; ++i ) printf( " %s", argv[i] ); printf( "/n" ); } int compare( const void *arg1, const void *arg2 ) { /* Compare all of both strings: */ return _stricmp( * ( char** ) arg1, * ( char** ) arg2 ); }
Output
boy deserves every favor good
相关文章推荐
- QuickSort和Hash Table在Sum题目中的应用.
- 题目1038:Sum of Factorials
- 大家都说是水题。。好吧,那我就从水题开始做。。自己独立的做。正好最近在辅导大二的数据结构,自己也加强下对栈的理解和应用。 第一次那么完全的独立完成OJ的题,激动呐!读题目理解就废了我好多的时间,虽说英语过了
- HDOJ 题目1258 Sum It Up(DFS)
- POJ 1845 Sumdiv(逆元的应用)
- POJ 题目2739 Sum of Consecutive Prime Numbers(水题)
- LeetCode算法题目:Sum Root to Leaf Numbers
- 题目1028:继续畅通工程(最小生成树应用)
- 排序算法--从头说12种排序算法:原理、图解、动画视频演示、代码以及笔试面试题目中的应用
- 题目1044:Pre-Post(递归的 4000 经典应用)
- POJ 1845-Sumdiv【经典数学题目---求因子和】
- 典型算法与ACM题目解析(3)—记忆化搜索的应用
- LeetCode: 关于Sum的题目合集
- Linq中Group和Sum的应用
- 12种排序算法:原理、图解、动画视频演示、代码以及笔试面试题目中的应用
- ES6原生Promise的所有方法介绍(附一道应用场景题目)
- 一道很有意思的题目,计算sum
- POJ 题目1564 Sum It Up(DFS,去重)
- leedcode做题总结,题目Two Sum2011-03-13
- 单调队列的一个应用——求解连续区间最大值(HDU Max Sum of Max-K-sub-sequence)