题目:
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
思考:
递增排序,从左往右数逐渐增大,而且不会出现重复的数字。当有多对数字和等于S的时候,如何选出乘积最小的那个呢?
说明一种情况,设有两个数x, y。
若x为矩形的长,y为矩形的宽。当x + y 为定值时,怎么样才能使矩形的面积最大呢?
相信大家都知道是当矩形的长和宽相等的时候,矩形的面积最大。此时,矩形的面积为xy,就是这两个数的乘积。
那么,考虑极限情况,当x 和 y 中的某一个数字为0时,x 和 y的乘积最小。
可以推广开来得到,当x + y为定值时,|x - y| 的值越小,x 和 y 的乘积越大;|x - y| 的值越大,x 和 y 的乘积越小。———结论1
(推理的过程不是十分的严谨,不过结论是这样的。用数学方法解决,就是另x + y = z; x * y = x * (z - x) = - + xz 配方之后得到
画出曲线,就可以知道矩形面积的变化规律,就是上述所提到的结论1)
从最左边的一个数字开始,与最右边的数字相加,如果相加的数大于所要得到的和,那么继续与次右边的数相加。如果相加得到的数小于所要得到的和,就不在考虑左边这个数字与其他数字的结合了。因为,左边这个数字再与右侧更小的数字结合,也不可能得到符合条件的数字。依次对每一个左侧的数进行这样的操作,当找到符合条件的时,退出循环,返回结果。
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int len = array.size();
vector<int> solve;
if(len < 2) return solve;
int left = 0;
int right = len - 1;
int flag = 1;
while(flag && left < right) {
int i = 0;
while(i < right - left) {
if(array[left] + array[right - i] == sum) {
solve.push_back(array[left]);
solve.push_back(array[right - i]);
flag = 0;
break;
}
else if(array[left] + array[right - i] > sum){
i++;
}
else {
break;
}
}
left++;
}
return solve;
}
};