-
题目描述:
- 输入一个递增排序的数组和一个数字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
最直观的就是暴力的方式,先在数组中固定一个位置,在依次判断数组中其余n-1个数字与这个数字的和是否符合题意。代码如下。复杂度为O(n^2).
-
-
//暴力迭代 void solution_1(int arr[],int len,int s,int *num1,int *num2) { if(arr == NULL || len <= 1) { return; } int i,j; for(i = 0; i < len; i++) { for(j=i+1;j < len; j++) { if(arr[i]+arr[j] == s) { *num1 = arr[i]; *num2 = arr[j]; return; } } } } void func(int arr[],int len,int index,int s,int *num1,int *num2) { if(index == len-1) { return; } for(int i = index + 1; i < len; i++) { if(arr[i] + arr[index] == s) { *num1 = arr[index]; *num2 = arr[i]; return; } } func(arr,len,index+1,s,num1,num2); } //暴力递归 void solution_2(int arr[],int len,int s,int *num1,int *num2) { if(arr == NULL || len <= 1) { return; } int index = 0; func(arr,len,index,s,num1,num2); }
显然上面的解法是不可取的,因为并没有利用到数组升序的性质。其实我们可以定义两个指针,low和high,分别指向数组首尾,并把两个指针所指向的数字求和,若和小于s,low指针后移,若和大于s,high指针前移。
代码:
#include<stdio.h> #include<stdlib.h> bool FindNumber(int arr[],int len,int s,int *num1,int *num2) { if(arr == NULL || len <= 1) { return false; } int low = 0,high = len-1; while(low < high) { if(arr[high] + arr[low] == s) { *num1 = arr[low]; *num2 = arr[high]; return true; }else if(arr[low]+arr[high] < s) { low++; }else { high--; } } return false; } int main() { int n,s; while(scanf("%d %d",&n,&s) != EOF) { int *arr = (int*)malloc(sizeof(int)*n); if(!arr) { exit(-1); } int i; for(i = 0; i < n; i++) { scanf("%d",arr+i); } int num1,num2; if(FindNumber(arr,n,s,&num1,&num2)) { printf("%d %d\n",num1,num2); }else { printf("-1 -1\n"); } free(arr); } return 0; }
-
-