面试题41:和为S的两个数字和为S的连续整数序列

本文介绍两种算法:一种是在有序数组中找到两数之和为指定值的方法;另一种是找出所有连续整数序列,使其和为给定值。
1.题目:输入一个递增排序的数组和数字S,在数组中找到两个数字使他们的和为S,如果存在多对数字的和为S,则输出其中的一对即可。
分析:

例如对于数组{1,2,4,7,11,15},以及要找的和为S,我们可以设置两个指针,第一个指针指向的是数组的起始位置的值1,第二个指针指向的是末尾的数字15,计算两个指针指向的数字的和,为16,判断与S的大小关系,如果等于S,则刚好找到,如果比S小,则前面的指针向前移动一个位置,如果比S大,则后面的指针往前移动一个位置。因为是递增的序列,最后一个指针的额位置已经不能继续往后移动,前面的指针往后移动的结果就是增大两个数的和,后面的指针往前移动是缩小两个数的和。当前判断是比S大,则后面的指针往前移动,指向11,重新计算两个指针指向的数的和为12,小于15,则此时前面的额指针往前移动指向2,重新计算两个数的和为13,小于15,前面的指针继续向前移动,此时指向4,计算两个数的和为15,刚好等于15,则4和11即是我们要找的符合条件的两个数。





连续数字的情况
2.题目,输入一个正数S,打印出所有和为S的连续整数序列(至少还有两个数).例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出三个连续的序列1-5,4-6,7-8.
分析:
可以采用上面的类似的解法,用small和big分别指向起始较小的数和最后结束最大的数。计算small到big的之间的数的和,如果和比S大,则应该丢弃当前较小的small值,如果比S小,则应该增加big的值,如果等于S,那最好。
例如分析和为9的连续整数序列,small和big的初始值分别为1和2,则初始的和为3,比9小,增大big为3,和为6小于9,继续增大big,何为10大于9,则此时丢掉small,small为2,此时和刚好为9,打印出small和big之间的数2,3,4.继续增大big,发现2-5之间的和为14,大于9,丢掉此时的small,3-5之间的值为12,比9大,继续丢点此时的small,4-5的和为9,满足条件,打印4,5.此时由于small的值已到达9的一半左右,后续再无可能有满足条件的数字。结束

源码:

/**
		* 功能说明:找到和为S的数字
		* 作者:K0713
		* 日期:2016-9-25
		**/

#include<iostream>
using namespace std;

bool FindTwoNumberOfS(int *a, int length, int S, int* number1, int* number2)
{
	bool found = false;
	if (length < 1 || number1 == NULL || number2 == NULL)
		return found;
	int head = 0;
	int tail = length - 1;
	int sum = 0;
	while (head < tail)
	{
		sum = a[head] + a[tail];
		if (sum == S)
		{
			*number1 = a[head];
			*number2 = a[tail];
			found = true;
			break;//找到第一个就停止不找了
		}
		else if (sum>S)//比S大,后面的指针向前移动
		{
			tail--;
		}
		else//比S小,前面的指针向后移动
		{
			head++;
		}
	}
	return found;
}
//打印连续序列
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;//small为中间值时已不能满足条件
	int curSum = small + big;

	while (small < middle)
	{
		if (curSum == sum)
			PrintContinuousSequence(small, big);

		while (curSum > sum && small < middle)//太大了要丢掉前面的small
		{
			curSum -= small;
			small++;

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

		big++;
		curSum += big;
	}
}

int main()
{
	int data[] = { 1, 2, 4, 7, 11, 15 };
	int num1, num2;
	bool result = FindTwoNumberOfS(data, sizeof(data) / sizeof(int), 15, &num1, &num2);
	cout << "------------------------------" << endl;
	cout << "1.和为15的两个数字:" << endl;
	if (result == true)
		cout << "number1: " << num1 << "   number2: " << num2 << endl;
	else
		cout << "none" << endl;

	cout << "------------------------------" << endl;
	cout << "2.和为15的连续正数序列:" << endl;
	FindContinuousSequence(15);
	system("PAUSE");
	return 0;
}




连续数字的情况
2.题目,输入一个正数S,打印出所有和为S的连续整数序列(至少还有两个数).例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以结果打印出三个连续的序列1-5,4-6,7-8.
分析:
可以采用上面的类似的解法,用small和big分别指向起始较小的数和最后结束最大的数。计算small到big的之间的数的和,如果和比S大,则应该丢弃当前较小的small值,如果比S小,则应该增加big的值,如果等于S,那最好。
例如分析和为9的连续整数序列,small和big的初始值分别为1和2,则初始的和为3,比9小,增大big为3,和为6小于9,继续增大big,何为10大于9,则此时丢掉small,small为2,此时和刚好为9,打印出small和big之间的数2,3,4.继续增大big,发现2-5之间的和为14,大于9,丢掉此时的small,3-5之间的值为12,比9大,继续丢点此时的small,4-5的和为9,满足条件,打印4,5.此时由于small的值已到达9的一半左右,后续再无可能有满足条件的数字。结束
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值