和为S的两个数字 and 和为s的连续正整数序列

/*
环境 winxp ,vc++6.0
题目:和为S的两个数字 and 和为s的连续正整数序列
*/
/*
题目出处:《剑指off——名企面试官精讲典型编程题》P214
*/
/*
题目1:输入一个递增排序的数组和一个数字 S ,在数组中查找两个数,使得它们的和正好是 s,如果有多对数字等于s,输出任意一对即可。
题目2:输入一个正数 s,打印出所有和为s的连续正整数序列(至少含有两个数)。例如输入15,由于1+2+3+4+5 = 4+5+6 = 7+8 =15 因此输出3个连续序列1~5,4~6和7~8
*/

/*
题目1解题思路,用两个指针分别指向数组的头尾,如果头尾和大于sum,就把尾指针往前移动,如果头尾和小于sum,就把头指针往后移动
*/

/*
题目2解题思路1:根据题目1,我们可以用两个指针small和big初始化指向1和2,然后如果他们的和小于sum,++big;如果和大于sum,++small,直到small<(sum+1)/2
题目2解题思路2:虽然题目1的思路我想到了,但是做题目2的时候确实没注意联系上下文,我的思路是这样的,最长的序列长度应该是从1开始加到n的,也即 (1+n)*n/2=sum
				那么我们从长度为 2 的序列和开始到 长度为 n 的序列和,那么这个该怎么算,我们其实可以根据连续序列和的特点来计算,如果序列个数是奇数,
				只需要能整除奇数就可以了,如果是整数的话会比较麻烦一点,比如有序列2345,也即sum为14的情况,这个时候长度是4,那么我们只要用14/4=3;那么 14=(4-1)*3+(3+4/2)
*/

#include<iostream>
#include<math.h>
using namespace std;

class Solution
{
public:
	//solution for subtitle 1
	bool FindNumbersWithSum(int *arr, int length, int sum)
	{
		if(arr==NULL || length<2)
			return false;

		int head = 0;
		int tail = length-1;

		while(head<tail)
		{
			if((arr[head]+arr[tail])>sum)
			{
				--tail;
			}
			else if((arr[head]+arr[tail])<sum)
			{
				++head;
			}
			else
			{
				//arr[head]+arr[tail]==sum
				return true;
			}
		}
		return false;
	}

	//solution 1 for subtitle 2, this solution from《剑指offer——名气面试官精讲典型编程题》p217
	void FindContinuousSequence(int sum)
	{
		if(sum<3)
			return ;

		int small = 1;
		int big = 2;
		int middle = (sum+1)/2;
		
		int curSum = small + big;
		while(small < middle)
		{
			if(curSum == sum)
				PrintContinousSequence(small,big);
			
			while(curSum>sum && small<middle)
			{
				curSum -= small;
				++small;

				if(curSum == sum)
					PrintContinousSequence(small,big);

			}

			big++;
			curSum += big;
		}
	}

	void FindContinuousSequence2(int sum)
	{
		if(sum<3)
			return ;

		//the max length of countinous sequence
		int length =(int)sqrt(2*sum);

		for(int i=2; i<=length; ++i)
		{

			int average = sum/i;
			//i is odd num
			if( i & 0x1)
			{
				if(sum%i ==0)
				{
					PrintContinousSequence(average-i/2, average + i/2);
				}
			}
			else
			{
				int tempSum = average*(i-1) + average+i/2;
				if(tempSum == sum)
				{
					PrintContinousSequence(average-i/2+1, average + i/2);
				}
			}
		}

	}


private:
	void PrintContinousSequence(int small, int big)
	{
		while(small<=big)
		{
			cout<<small<<" ";
			++small;
		}
		cout<<endl;
	}
};

int main()
{

	Solution so;

	//int arr[5] = {1,3,4,7,9};
	int *arr = NULL;
	
	if(so.FindNumbersWithSum(arr,5,6))
		cout<<"YES"<<endl;
	else
		cout<<"NO"<<endl;

	for(int i=3;i<20;i++)
	{
		cout<<"i="<<i<<endl;
	//	cout<<"method 1: ";
		so.FindContinuousSequence(i);
	//	cout<<"method 2:";
		so.FindContinuousSequence2(i);
		cout<<endl;
	}
	getchar();
	getchar();
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值