[剑指offer]面试题41:和为s的两个数字VS和为s的连续正数序列

Posted Wecccccccc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[剑指offer]面试题41:和为s的两个数字VS和为s的连续正数序列相关的知识,希望对你有一定的参考价值。

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

代码如下:

bool FindNumbersWithSum(int data[], int length, int sum, int *num1, int *num2)
{
	bool found = false;
	if (length < 1 || num1 == nullptr || num2 == nullptr) 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的两个数)
● 特殊输入测试(表示数组的指针为NULL指针)

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

代码如下:

void FindContinousSequence(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) PrintContinousSequence(small, big);

		while (curSum > sum && small < middle)
		{
			curSum -= small;
			small++;

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

void PrintContinousSequence(int small, int big)
{
	for (int i = small; i <= big; i++) cout << i << " ";
	cout << endl;
}

这段代码用到了一个小技巧:
通常我们可以用循环求一个连续序列的和,但考虑到每一次操作之后的序列和操作之前的序列相比大部分数字都是一样的,只是增加或者减少了一个数字,因此我们可以在前一个序列的和的基础上求操作之后的序列的和。这样可以减少很多不必要的运算,从而提高代码的效率。

测试用例:
● 功能测试(存在和为 s 的连续序列,如 9、100 等;不存在和为 s的连续序列,如4、0)。
● 边界值测试(连续序列的最小和3)
本题考点:
● 考查思考复杂问题的思维能力。应聘者如果能够通过一两个具体的例子找到规律,解决这个问题就容易多了。
● 考查知识迁移的能力。应聘者面对第二个问题的时候,能不能把解决第一个问题的思路应用到新的题目上,是面试官考查知识迁移能力的重要指标。

以上是关于[剑指offer]面试题41:和为s的两个数字VS和为s的连续正数序列的主要内容,如果未能解决你的问题,请参考以下文章

剑指OFFER----面试题57. 和为s的两个数字

剑指offer题目--面试中的各项能力章

剑指offer 面试57题

剑指Offer对答如流系列 - 和为s的数字

《剑指offer》JZ41 ~ JZ50

剑指offer-面试题57_2-和为s的连续正数序列-穷举法