27 和为S的两个数字

0 引言

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

1 抽象问题具体化

举例: 序列为{1,2,3,4,5,6,7,8,9}, 和为10

解答:如下图所示,一头一尾两个指针分别运动,找到和为10的两个数,并比较其乘积,得到乘积最小的两个数作为结果输出。

  1*9 = 9;

  2*8 = 16;

  3*7 = 21;

  4*6 = 24;

  

2 具体问题抽象分析

算法描述:设序列为array,和为sum

(1)将两个指针初始化为序列头(p)尾(q)两项;

(2)如果两个数的和小于sum(array[p] + array[q] < sum),则考虑增大p,使得和值增大;

(3)如果两个数的和大于sum(array[p] + array[q] > sum),则考虑减小q,使得和值减小;

(4)如果两个数的和等于sum(array[p] + array[q] == sum),则考虑增大p或者减小q,使得遍历继续,同时根据两数的乘积更新最小乘积以及输出值;

(5)返回结果

3 demo

/* 寻找递增序列中和为sum的两个数
* 输入1: vector<int> array,递增序列
* 输入2: int sum, 和
* 输出:  vector<int>格式,两个数,其和等于sum,乘积最小
* 算法思路描述:一头一尾两个指针分别运动,记录其和值中乘积最小的一个
*/
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
    vector<int> twoNums{0,0};
    if(array.size() < 2){
        twoNums.clear();
        return twoNums;
    }
    int minMultiplication = pow(array[array.size()-1],2);
    for(int p=0, q=(int)array.size()-1; p != q;){
        if(array[p] + array[q] < sum)
            ++ p;
        else if(array[p] + array[q] > sum)
            -- q;
        else{
            if(array[p] * array[q] <= minMultiplication){
                minMultiplication = array[p] * array[q];
                twoNums[0] = array[p];
                twoNums[1] = array[q];                   
            }                
            -- q; // 或者++ p;
        }          
    }
    if(twoNums[0] == 0 && twoNums[1] == 0)
        twoNums.clear();        
    return twoNums;        
}

4 代码优化

posted @ 2018-12-22 21:19  十步一杀2017  阅读(177)  评论(0编辑  收藏  举报