【LeetCode & 剑指offer刷题】数组题2:57 有序数组中和为s的两个数(167 Two Sum II - Input array is sorted)
【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)
57 有序数组中和为s的两个数
题目描述
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
对应每个测试案例,输出两个数,小的先输出。
#include <climits>
class Solution
{
public:
vector<int> FindNumbersWithSum(vector<int> a,int sum)
{
if(a.size()<2) return vector<int>();
int min_product = INT_MAX;
int left = 0, right = a.size()-1;
int a1,a2;
bool find_flag = false;
while(left < right) //从两边开始往中间扫描
{
int cursum = a[left] + a[right];
if(cursum > sum) right--;
else if(cursum < sum) left++;
else
{
//因为对于递增序列,一定有x*y < (x+a)*(y-a),故这里其实可以不用判断
//从两边开始往中间扫描时,找到的第一个即为乘机最小的一对数
if(a[left]*a[right] < min_product)
{
find_flag = true;
min_product = a[left]*a[right];
a1 = a[left];
a2 = a[right];
}
left++; //继续扫描
}
}
if(find_flag) return vector<int>{a1,a2};
else return vector<int>();
}
};
拓展:和为S的连续正数序列
题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列(指1、2、3、4等)。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
class Solution
{
public:
vector<vector<int> > FindContinuousSequence(int sum)
{
vector<vector<int>> result;
if(sum < 3) return result; //至少需包含两个数
int left = 1, right = 2; //序列从1开始
while(left < right) //注意从开头开始扫描,直到left与right相遇
{
int cursum = (left+right)*(right - left + 1)/2; //用等差数列的求和公式
if(cursum < sum) right++;
else if(cursum > sum) left++;
else
{
vector<int> temp;
for(int i = left; i <= right; i++)
temp.push_back(i);
result.push_back(temp); //push符合要求的连续正数序列
left++; //继续下个序列的寻找
}
}//最后退出循环时,left = right = sum/2+1的位置,比如找10,最后指向 5、6,再均指向6,退出循环
return result;
}
};