剑指Offer----面试题41(1):和为s的两个数字

本文介绍两种高效算法来寻找一个递增排序数组中和为特定值S的两个数。第一种方法采用双重循环,时间复杂度为O(n²);第二种方法使用双指针技巧,从数组两端向中间逼近,实现O(n)的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:


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


方法一:


分析


先固定其中的一个数字,再依次扫描该数字后边的数字,判断这两个数字的和是否为s,时间复杂度为O(n2)。

代码:


#include<iostream>

using namespace std;

void Function1(int *arr, int length, int s)
{
	if (arr == nullptr || length<=1)
	{
		cout << "输入的数组不符合条件" << endl;
		return;
	}

	for (int i = 0; i < length - 1; ++i)
	{
		for (int j = i + 1; j < length; ++j)
		{
			if (arr[i] + arr[j] == s)
			{
				cout << "找到一对值的和为s,分别为:" << arr[i] << "\t" << arr[j] << endl;
				return;
			}
		}
	}

	cout << "没有找到" << endl;
}

void test1()
{
	cout << "==================test1:{1,2,4,7,11,15}==================" << endl;
	int arr[] = { 1, 2, 4, 7, 11, 15 };
	int s = 15;
	Function1(arr, sizeof(arr) / sizeof(int), s);
	cout << endl;
}


int main()
{
	test1();

	system("pause");
	return 0;
	
}

运行结果:
==================test1:{1,2,4,7,11,15}==================
找到,数值分别为:4     11

请按任意键继续. . .

方法二


分析


用两个指针,一个指向头,一个指向尾,求所指数字的和,如果等于s,直接输出两个数字;如果小于s,将头指针向后移动;如果大于s,尾指针向前移动,直至其和为s或者尾指针大于头指针。

这种算法的时间复杂度为O(n)。

源码

#include<iostream>

using namespace std;

void Function2(int *arr, int length, int s)
{
	if (arr == nullptr || length <= 1)
	{
		cout << "输入的数组不符合要求" << endl;
		return;
	}

	int *pBegin = arr;
	int *pEnd = arr + length - 1;

	while (pBegin < pEnd)
	{
		long long sum = *pBegin + *pEnd;
		if (sum == s)
		{
			cout << "找到,数值分别为:" << *pBegin << "\t" << *pEnd << endl;
			return;
		}
		else if (sum > s)
		{
			--pEnd;
		}
		else if (sum < s)
		{
			++pBegin;
		}
	}

	cout << "没有找到" << endl;
}

// 存在和为s的两个数字,这两个数字位于数组的中间
void test11()
{
	cout << "==================test1:存在和为s的两个数字,这两个数字位于数组的中间==================" << endl;
	int arr[] = { 1, 2, 4, 7, 11, 15 };
	int s = 15;
	Function2(arr, sizeof(arr) / sizeof(int), s);
	cout << endl;
}

// 存在和为s的两个数字,这两个数字位于数组的两段
void test12()
{
	cout << "==================test2:存在和为s的两个数字,这两个数字位于数组的两段==================" << endl;
	int arr[] = { 1, 2, 4, 7, 11, 16 };
	int s = 17;
	Function2(arr, sizeof(arr) / sizeof(int), s);
	cout << endl;
}

// 不存在和为s的两个数字
void test13()
{
	cout << "==================test3:不存在和为s的两个数字==================" << endl;
	int arr[] = { 1, 2, 4, 7, 11, 15 };
	int s = 20;
	Function2(arr, sizeof(arr) / sizeof(int), s);
	cout << endl;
}

// 鲁棒性测试
void test14()
{
	cout << "==================test4:鲁棒性测试==================" << endl;
	Function2(nullptr, 0, 0);
	cout << endl;
}
int main()
{
	test11();
	test12();
	test13();
	test14();

	system("pause");
	return 0;

}

输出结果:
==================test1:存在和为s的两个数字,这两个数字位于数组的中间==================
找到,数值分别为:4     11

==================test2:存在和为s的两个数字,这两个数字位于数组的两段==================
找到,数值分别为:1     16

==================test3:不存在和为s的两个数字==================
没有找到

==================test4:鲁棒性测试==================
输入的数组不符合要求

请按任意键继续. . .



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值