题目:
在一个递增排序的数组中,找到两个数字和为S,如果有多组,则返回乘积最小的那两个数字。
思路:
排序好的数组。用两个指针p,q分别指向首尾两个数字。如果和小于S,则指针p向右移动一位继续比较。
如果和大于S,则指针q向左移动一位继续比较。
如果相等,则p和q分别向右和左移动一位寻找下一组数字。
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int len = array.size();
vector<int> res;
if(len == 0) return res;
int mult = INT_MAX;
int p = 0; int q = len -1;
while(p<q)
{
int sum_pq = array[p] + array[q];
if(sum_pq > sum){
q--;
}
else if(sum_pq < sum){
p++;
}
else{
int cur = array[p] * array[q];
if(cur < mult){
res.clear();
res.push_back(array[p]);
res.push_back(array[q]);
mult = cur;
}
p++;
q--;
}
}
return res;
}
};
进一步分析:对于一个和为S的两个数,肯定是两个数之间相差越大越好。所以其实找到的第一组数字就是解。
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int len = array.size();
vector<int> res;
if(len == 0) return res;
int p = 0; int q = len -1;
while(p<q)
{
int sum_pq = array[p] + array[q];
if(sum_pq > sum){
q--;
}
else if(sum_pq < sum){
p++;
}
else{
res.push_back(array[p]);
res.push_back(array[q]);
break;
}
}
return res;
}
};
进阶题目:
输入一个正数S,打印出所有和为S的连续正数序列(至少含有两个数)。例如输入15,由于 1+2+3+4+5= 4+5+6=7+8=15,所以有三个序列,均需保存。
思路:
与上题类似,定义两个指针p,q 分别指向当前正数序列的最左端和最右端。q的范围至多到S的一半,q<=(S+1)/ 2,参考S = 5, 序列为 2,3.
用sum_temp保存当前序列之和。如果sum_temp小于S,q向后移动一位。当sum_temp大于S,需要右移p,也要重新计算当前序列之和。为了避免重新累加计算序列和,可以充分利用前面的sum_temp,即用sum_temp - p得到新的sum_temp,之后再更新p为p+1。
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int>> res;
if(sum <= 2) return res;
vector<int> eachres;
int i = 1;
int p = 1;
int q = 2;
int sum_temp = p+q;
while(q <= (sum+1)/2 && p < q){
if(sum_temp < sum){
q++;
sum_temp += q;
}
if(sum_temp > sum){
sum_temp = sum_temp - p;
p++;
}
if(sum_temp == sum){
eachres = FindOneSolution(p,q);
res.push_back(eachres);
eachres.clear();
sum_temp = sum_temp - p;
p++;
}
}
return res;
}
vector<int> FindOneSolution(int p , int q){
vector<int> res;
for(int i = p; i<=q; i++){
res.push_back(i);
}
return res;
}
};