51Nod 1001 数组中和等于K的数对

给出一个整数K和一个无序数组A,A的元素为N个互不相同的整数,找出数组A中所有和等于K的数对。例如K = 8,数组A:{-1,6,5,3,4,2,9,0,8},所有和等于8的数对包括(-1,9),(0,8),(2,6),(3,5)。
Input
第1行:用空格隔开的2个数,K N,N为A数组的长度。(2 <= N <= 50000,-10^9 <= K <= 10^9)
第2 - N + 1行:A数组的N个元素。(-10^9 <= A[i] <= 10^9)
Output
第1 - M行:每行2个数,要求较小的数在前面,并且这M个数对按照较小的数升序排列。
如果不存在任何一组解则输出:No Solution。
Input示例
8 9
-1
6
5
3
4
2
9
0
8
Output示例
-1 9
0 8
2 6
3 5

今天绝对是一个值得纪念的日子,我之前一直是个天不怕地不怕的主,因为自己会的太少,一直在做简单题,数据基本暴力就能解决,今天凌晨知道51Nod这个网站,注册了一个账户,下午看了这个题,本来的思路很简单,就是暴力。先排序,然后从第一个开始往后加,等于K就输出,首先这个思路肯定没问题,但是时间复杂度高呀,n^2,n最大为5万。不出意外,这样提交之后就Time limit exceeded。注意,这时候还剩两组数据超时。我稍微动了动脑子。假如说,排序后的第一个数字和某一个数字相加已经大于了K,这时候就不用再往后继续比较了,直接break,不就可以啦。我很开心呢。但是还是剩一组数据显示超时。这时候我就感觉51Nod厉害了。但我已经没办法啦。。但我这时候想法已经快接近到答案了,我意识到这个还超时,那就肯定不是用这个方法了,需要推翻整个的想法,答案估计是个线性的也就是n就可以了。但我想了很久,没办法百度了。才搜到了下面的这个方法。这个也是全场最佳。

1 #include <stdio.h>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int N = 50005;
 6 
 7 int k, n;
 8 int a[N];
 9 
10 int main() {
11   int i, j;
12   scanf("%d %d", &k, &n);
13   for (i = 0; i < n; i++) {
14     scanf("%d", &a[i]);
15   }
16   sort(a, a + n);
17   bool flag = false;
18   i = 0; j = n - 1;
19   while (i < j) {
20     n = a[i] + a[j];
21     if (n == k) { printf("%d %d\n", a[i++], a[j--]); flag = true; }
22     else if (n < k) { i++; }
23     else { j--; }
24   }
25   if (!flag) { puts("No Solution"); }
26 }

为什么我会说这是一个值得纪念的日子,因为我真的感觉到了竞赛的难点了,有的题,你也看得懂,有些思路,但是就是不对。需要优化什么的。

这个答案呢,我看了之后很惊奇,因为我刚刚学会自己写快速排序,看了前两行,我以为是利用快排的思路写的。看了答案我发现我对题目认识的还不到位,给定的集合互不相等,所以,一个数字只用检查一次就可以了,从两头不断的逼近,最终就可以找到所有的了,真的很棒。看懂答案的那一刻,很开心。保持这份对未知的好奇心,我希望他可以让我走得更远。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值