剑指offer 41 - 和为s的两个数字VS为s的连续正数序列

题目:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,输出任意一对即可。

例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。

思路整理一下:最初我们找到数组的第一个数字和最后一个数字。首先定义两个指针,第一个指针指向数组的第一个(也就是最小的)数字,第二个指针指向数组的最后一个(也就是最大的)数字。当两个数字的和大于输入的数字时,把较大的数字往前移动;当两个数字的和小于数字时,把较小的数字往后移动;当相等时,打完收工。这样扫描的顺序是从数组的两端向数组的中间扫描。

 

#include<iostream>
using namespace std;

bool FindNumbersWithSum(int* data,int length,int sum,int *num1,int* num2)
{
	if(data==NULL || length<1  ||  num1==NULL  || num2==NULL)
		return false;

	int p=0;
	int q=length-1;
	while(p<q)
	{
		long long curSum = data[p]+data[q];
		if(curSum==sum)
		{
			*num1=data[p];
			*num2=data[q];
			return true;
		}
		else if(curSum>sum)
			q--;
		else
			p++;

	}	
	return false;
}
void Test(char *testName,int* data,int length,int sum,bool  isExist)
{
	cout<<testName<<" ";
	int num1=0,num2=0;
	bool result = FindNumbersWithSum(data,length,sum,&num1,&num2);
	if(isExist == result) 
	{
		if(result)
		{
			if(num1+num2==sum)
				cout<<"Passed.\n";
			else
				cout<<"Failed.\n";
		}
		else
			cout<<"Passed.\n";
	}
	else
		cout<<"Failed.\n";
}

// 存在和为s的两个数字,这两个数字位于数组的中间
void Test1()
{
    int data[] = {1, 2, 4, 7, 11, 15};
    Test("Test1", data, sizeof(data) / sizeof(int), 15, true);
}

// 存在和为s的两个数字,这两个数字位于数组的两段
void Test2()
{
    int data[] = {1, 2, 4, 7, 11, 16};
    Test("Test2", data, sizeof(data) / sizeof(int), 17, true);
}

// 不存在和为s的两个数字
void Test3()
{
    int data[] = {1, 2, 4, 7, 11, 16};
    Test("Test3", data, sizeof(data) / sizeof(int), 10, false);
}

// 鲁棒性测试
void Test4()
{
    Test("Test4", NULL, 0, 0, false);
}
int main()
{
	 Test1();
    Test2();
    Test3();
    Test4();

    return 0;
}


2.输入一个整数s,输出所有连续序列(至少两个数字)和为s的序列,例如15,打印; 1+2+3+4+5 = 4+5+6 = 7+8    

设定small = 1,big =2;

如果从small到big的序列和curSum大于s,curSum减去small的值,small 加1  直到 curSum<=s

如果从small到big的序列和curSum小于s,big加1,curSum加上big的值  

循环终止条件 small<(s+1)/2

#include<iostream>
using namespace std;
void printContinuousSequence(int small,int big)
{
	for(int i=small;i<=big;i++)
		cout<<i<<" ";
	cout<<endl;
}
void FindContinuousSequence(int sum)
{
	if(sum<3)
		return ;
	int small = 1;
	int big = 2;
	int middle = (1+sum)/2;
	int curSum=small+big;
	while(small<middle)
	{
		if(curSum==sum)		
			printContinuousSequence(small,big);
			
		while(curSum>sum && small<middle)
		{
			curSum -=small;
			small++;

			if(curSum==sum)		
				printContinuousSequence(small,big);		
		}

		big++;
		curSum +=big;

	}
}
// ====================测试代码====================
void Test(char* testName, int sum)
{
    if(testName != NULL)
        printf("%s for %d begins: \n", testName, sum);

    FindContinuousSequence(sum);
}

int main(int argc, char* argv[])
{
    Test("test1", 1);
    Test("test2", 3);
    Test("test3", 4);
    Test("test4", 9);
    Test("test5", 15);
    Test("test6", 100);

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值