题目:
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得他们的和正好是s。如果有多对数字的和为s,输出任意一对即可。
最直接的做法:双重循环依次尝试,时间复杂度O(n^2)。
更好的方法:
1、在数组中选择两个数字(不妨设两个指针,一个指向最小元素,一个指向最大元素),如果它们的和等于输入的s,就找到了两个数字;
2、如果和小于s,由于已经排序,选择较小数字后面的数字,即第一个指针后移;
3、如果和大于s,选择较大数字前面的数字,即第二个指针前移。
bool FindNumbersWithSum(int data[],int length,int sum,int* num1,int* num2)
{
bool found=false;
if(length<1 || num1==NULL || num2==NULL)
return found;
int ahead=length-1;
int behind=0;
while(ahead>behind)
{
long long curSum=data[ahead]+data[behind];
if(curSum==sum)
{
*num1=data[behind];
*num2=data[ahead];
found=true;
break;
}
else if(curSum>sum)
ahead--;
else
behind++;
}
return found;
}
题目:
输入一个正数s,打印所有和为s的连续正数序列(至少包含两个数)。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以打印出3个连续序列1-5,4-6,7-8.
不妨设置small与big,分别初始化为1和2。
如果从small到big的序列和大于s,从序列中去除最小,即small++;如果小于s,那么增大big,即big++.
因为这个序列至少要两个数字,因此一直增加small到(1+s)/2。
void Print(int small,int big)
{
for(int i=small;i<=big;++i)
cout<<i;
cout<<endl;
}
void FoundContinoutsSequence(int sum)
{
if(sum<3)
return;
int small=1;
int big=2;
//比如15=7+8,最少两个数字相加,即可考虑sum的一半+-1
int middle=(1+sum)/2;
int curSum=small+big;
while(small<middle)
{
if(curSum==sum)
Print(small,big);
while(curSum>sum && small<middle)
{
curSum-=small;
small++;
if(curSum==sum)
Print(small,big);
}
big++;
curSum+=big;
}
}