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 代码优化