和为S的两个数字

来源:互联网 发布:矩阵相似性度量 编辑:程序博客网 时间:2024/06/05 06:37

题目描述

输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

输出描述:

对应每个测试案例,输出两个数,小的先输出。
分析:看到题目以后,首先想到的是利用一个两重循环遍历数组,找到和为S的两个数,然后在遍历的过程中通过一个条件语句,将成绩最小的两个数存储起来,下面是按照这个思路第一次写的代码:
/* 双重循环,直接查找最小乘积,程序段错误,可能数组越界,堆栈溢出class Solution {public:    vector<int> FindNumbersWithSum(vector<int> array,int sum) {        vector<int> equalsum;        vector<int>::iterator pr, qr;        int t=0;        for(vector<int>::iterator p=array.begin(); p<array.end(); ++p)            {            for(vector<int>::iterator q=p+1; q<array.end(); ++q)                {                if(*p+*q==sum)                    {                    t=(*p)*(*q);pr=p;qr=q;                    if((*p)*(*q)<t)                        {                        pr=p;                        qr=q;                    }                }            }        }        equalsum.push_back(*pr);        equalsum.push_back(*qr);        return equalsum;    }};*/

但是上面的代码在牛客网上运行报错,可能是时间复杂度的问题?代码写的也不够好。于是参考了别人写的代码,对题目又进行了一顿分析:
设数组中的两个数x和y,其中x+y=S,x<y,要求的是x*y的最小值。
y=S-x,则x*y=x*(S-x)=-x2+x*S,为一个一元二次方程,函数坐标轴为x=-b/2a=2/S,其中由于
x+y=S,x<y
所以x的取值范围小于2/S,则x变大时,x*y也变大,所以第一个满足条件的x和y的值即为乘积最小的值。
分别在数组头尾设置两个指针i和j,程序中当array[i]+array[j]<sum时,指针i向前移动,即++i
array[i]+array[j]>sum时,指针j向后移动,即--j.
代码如下:
/*从两端向中间查找,找到的第一对数即为最小乘积*/class Solution {public:    vector<int> FindNumbersWithSum(vector<int> array,int sum) {        int n=array.size();        vector<int> res;        int i=0,j=n-1;        while(i<j)            {            if(array[i]+array[j]==sum)            {                res.push_back(array[i]);                res.push_back(array[j]);                break;            }            else if(array[i]+array[j]<sum)                ++i;            else                --j;        }        return res;    }};