数组中和为 s 的数对 && 和为 s 的连续正数序列

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

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

    现在数组中选择两个数字,如果它们的和等于输入的 s,就找到了要找的数字。如果和小于 s,我们希望两个数的和再大一点。由于数组已经排好序了,可以考虑选择较小数字的后面的数字。因为排在后面的数字要大一些,那么两个数字的和也要大一些,就有可能等于输入的数字 s。同样,当两个数字的和大于输入的数字的时候,可以选择较大数字前面的数字,因为拍在数组前面的数字要小一些。

    以数组 {1, 2, 4, 7, 11, 15} 及期待的和 15为例详细分析一下:首先定义两个指针,第一个指针指向数组中的第一个元素(也是最小的数字 1);第二个指针指向数组的最后一个(也是最大的)数字 15. 这两个数字的和 16 大于 15 ,因此将第二个指针向前移动一个数字,让它指向 11 。这个时候两个数字 1 和 11 的和为 12 小于 15 。接下来将第一个指针向后移动一个数字指向 2 。此时两个数的和为 13,还是小于 15 。再一次向后移动第一个指针指向 4, 数字 4 和 11 的和刚好是 15 。正是期待的结果,输出 4 和 11 。 

//给定一个数组和一个整数,输入数组中和为该整数的数对
#include<iostream>
using namespace std;

bool FindNumbersWithSum(int *data, int length, int sum)
{
	bool found = false;		//指示数组中是否包含两个和为输入整数的数字
	if(data == NULL || length <= 0)
		return found;
	
	int ahead = length - 1;
	int behind = 0;
	while(ahead > behind)
	{
		int currentSum = data[ahead] + data[behind];
		if(currentSum == sum)
		{
			cout << data[ahead] << " + " << data[behind] << " = " << sum << endl;
			found = true;
			break;
		}
		else if(currentSum > sum)	//当前的和较大时,向后移动ahead指针(即使较大的值减小)
			ahead--;
		else	//当前的和较小时,向前移动 behind 指针(即使较小的值大一点)
			behind++;
	}
	return found;
}

int main()
{
	int data[] = {1, 2, 4, 7, 11, 15};
	bool flag = FindNumbersWithSum(data, 6, 25);
	cout << flag << endl;

	system("pause");
	return 0;
}

题目 2:

输入一个正整数 s, 打印出所有和为 s 的连续正数序列(至少含有两个数)。例如,输入 15,由于 1+2+3+4+5 = 5+6+7 = 7+8 = 15, 所以结果打印出 3 个连续序列: 1~5, 4~7, 7~8 。

    根据 《和为 s 的两个数字》的思路,也考虑两个数 small 和 big 分别表示序列的最小值和最大值。首先把 small 初始化为 1,big 初始化为 2 。如果从 small 到 big 的序列的和大于 s,可以从序列中去掉较小的值,也就是增大 small 的值。如果从 small 到 big 的序列的和小于 s,可以增大 big,让这个序列包含更多的数字。因为这个序列至少要有两个数字,small 一直增加到 (1+s)/2 即可。

以求和为 9 的所有连续序列为例,先把 small 初始化为 1,big 初始化为 2. 此时介于 small 和 big 之间的序列为{1, 2},序列的和为 3,小于 9,将 big 增加1 变成 3,此时序列为 {1, 2, 3}。由于序列的和是 6,仍然小于 9,接下来在增加 big 变成 4,介于 small 和 big 之间的序列为 {1, 2, 3, 4}。由于序列的和 10 大于 9,需要删除序列中的一些数。于是增加 small 变成 2.此时的序列变为 {2, 3, 4}。序列的和刚好为 9. 找到了第一个和 为 9 的连续序列,把它打印出来。接下来再增加 big, 重复前面的过程,可以找到第二个和为 9 的连续序列 {4, 5}。。。。

//打印出所有和为 s 的连续正数序列
#include<iostream>
using namespace std;

void PrintContinuousSequence(int small, int big)
{
	if(small < big)
	{
		for(int i = small; i <= big; i++)
			cout << i << " ";
		cout << endl;
	}
	else 
		return;
}

void  FindContinuousSequence(int sum)
{
	if(sum < 3)
		return;
	int small = 1;
	int big = 2;
	int middle = (1 + sum) / 2;
	int currentSum = small + big;
	
	while(small < big && big < sum)
	{
		
		if(currentSum == sum)
			PrintContinuousSequence(small, big);
		while(currentSum > sum && small < middle)
		{
			currentSum -= small;
			small++;
			if(currentSum == sum)
				PrintContinuousSequence(small, big);
		}
		
			big++;
			currentSum += big;
	}
}

int main()
{
	FindContinuousSequence(100);

	system("pause");
	return 0;
}


转载于:https://my.oschina.net/u/2260265/blog/350291

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值