题目:输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。输出描述,对应每个测试案例,输出两个数,小的先输出。
代码如下:
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
map<int,int> map1;
map<int,int> resultmap;
map<int,int>::iterator iter;
vector<int> vect;
int i;
for(i=0;i<array.size();i++)
{
if(map1.count(array[i]))
resultmap[array[i]]=sum-array[i];
else
map1[sum-array[i]]=array[i];
}
int minval=INT_MAX,val,num1=0,num2=0;
for(iter=resultmap.begin();iter!=resultmap.end();++iter)
{
val=(iter->first)*(iter->second);
if(val<minval)
{
num1=iter->first<iter->second?iter->first:iter->second;
num2=iter->first>iter->second?iter->first:iter->second;
minval=val;
}
}
if(minval!=INT_MAX)
{
vect.push_back(num1);
vect.push_back(num2);
}
return vect;
}
};
分析一下,采用的是一个map去记录遍历过的数字,key为sum-data[i],value为该值,以便在后面出现sum-data[i],可以记录下来,这样一对就是和为sum的值对。存在resultmap中。然后寻找乘积最小的对数。时间复杂度的话我觉得是遍历O(n*lgn),count应该是lgn。
但好像并没有用到题设中的数组是排序的这一条件。于是看了书上的想法。果然精简。
class Solution {
public:
vector<int> FindNumbersWithSum(vector<int> array,int sum) {
int i=0,j=array.size()-1;
map<int,int> resultmap;
map<int,int>::iterator iter;
vector<int> vect;
while(i<j)
{
if(array[i]+array[j]==sum)
{
resultmap[array[i]]=array[j];
i++;
j--;
}
else if(array[i]+array[j]<sum)
i++;
else
j--;
}
int minval=INT_MAX,val,num1=0,num2=0;
for(iter=resultmap.begin();iter!=resultmap.end();++iter)
{
val=(iter->first)*(iter->second);
if(val<minval)
{
num1=iter->first;
num2=iter->second;
minval=val;
}
}
if(minval!=INT_MAX)
{
vect.push_back(num1);
vect.push_back(num2);
}
return vect;
}
};
思路也很清楚,因为是排序数组,如果array[i]+array[j]>sum;说明大了,j减一个,如果小了,i加一个。
该题还有一种扩展:
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序。
同时考虑small和big分别为最小,最大值。如果从small到big的最大值小于sum,则增加big,否则增加small(相当于丢弃原来的small,值减小),代码如下:
class Solution {
public:
vector<vector<int> > FindContinuousSequence(int sum) {
vector<vector<int> > result;
int small=1;
int big=2;
int j;
int middle=(1+sum)/2;
int cursum=small+big;
while(small<middle)
{
if(cursum==sum)
{
InsertToVect(result,small,big);
cursum-=small;
small++;
}
else if(cursum<sum)
{
big++;
cursum+=big;
}
else
{
cursum-=small;
small++;
}
}
return result;
}
void InsertToVect(vector<vector<int> > & v,int small,int big)
{
vector<int> vect;
int i;
for(i=small;i<=big;i++)
vect.push_back(i);
v.push_back(vect);
}
};