九度oj 题目1352:和为S的两个数字
- 题目描述:
- 输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
- 输入:
-
每个测试案例包括两行:第一行包含一个整数n和k,n表示数组中的元素个数,k表示两数之和。其中1 <= n <= 10^6,k为int第二行包含n个整数,每个数组均为int类型。
- 输出:
- 对应每个测试案例,输出两个数,小的先输出。如果找不到,则输出“-1 -1”
- 样例输入:
-
6 15 1 2 4 7 11 15
- 样例输出:
-
4 11
今天状态真是差劲
一开始的代码如下1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 int num[1000002]; 9 10 int main(int argc, char const *argv[]) 11 { 12 int n, k; 13 while(scanf("%d %d",&n,&k) != EOF) { 14 for(int i = 0; i < n; i++) { 15 scanf("%d",&num[i]); 16 } 17 int iptr = 0; 18 int mina = -1, minb = -1; 19 while(iptr < n) { 20 int p = k - num[iptr]; 21 int t = lower_bound(num, num + n, p) - num; 22 if(num[t] == p && t > iptr) { 23 mina = num[iptr]; 24 minb = p; 25 break; 26 } 27 iptr++; 28 } 29 printf("%d %d\n",mina, minb); 30 } 31 return 0; 32 }
思路很简单,用二分搜索找到另一个值在数组中的位置。结果反复提交都是错误
问题:lower_bound返回的是num[i]>=p的指针的最小值,
如果输入
5 2
1 1 1 2 5就会出错
改正
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 int num[1000002]; 9 10 int main(int argc, char const *argv[]) 11 { 12 int n, k; 13 while(scanf("%d %d",&n,&k) != EOF) { 14 for(int i = 0; i < n; i++) { 15 scanf("%d",&num[i]); 16 } 17 int iptr = 0; 18 int mina = -1, minb = -1; 19 while(iptr < n && num[iptr] * 2 <= k) { 20 int p = k - num[iptr]; 21 int t = upper_bound(num, num + n, p) - num - 1; 22 if(num[t] == p && t > iptr) { 23 mina = num[iptr]; 24 minb = p; 25 break; 26 } 27 iptr++; 28 } 29 printf("%d %d\n",mina, minb); 30 } 31 return 0; 32 }
其实此题还有一种更好的解法
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 int num[1000002]; 9 10 int main(int argc, char const *argv[]) 11 { 12 int n, k; 13 while(scanf("%d %d",&n,&k) != EOF) { 14 for(int i = 0; i < n; i++) { 15 scanf("%d",&num[i]); 16 } 17 int low = 0, high = n-1; 18 int mina = -1, minb = -1; 19 while(low < high) { 20 if(num[low] + num[high] == k) { 21 mina = num[low]; 22 minb = num[high]; 23 break; 24 } 25 else if(num[low] + num[high] < k) { 26 low++; 27 } 28 else { 29 high--; 30 } 31 } 32 printf("%d %d\n",mina, minb); 33 } 34 return 0; 35 }
注意找到的第一个便是乘积最小的!!!