算法习题14:输入一个已经按升序排序过的数组和一个数字

博客讨论了一道算法题,要求在已排序的数组中找到两个数,其和等于给定的目标值,且时间复杂度为O(n)。博主提到,由于数据已排序,可以通过双指针方法在O(n)时间内找到一对答案,而无法找出所有可能的组合。此外,还简要提到了不同类型的排序算法,如快速排序、堆排序等,并提供了一个排序算法的博客链接作为参考。

原题:

题目:输入一个已经按升序排序过的数组和一个数字,
在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。

---------------------------

但其是这道题如果考官再拿来考,应该会改成

输入一串数字以及一个和,从这串数字里找出和为这个值的一对数字?如果要找出所有的呢?

-----------------------------------

所以这道题就需要先进行排序,然后求和,而排序又涉及到了多种算法,是采用O(NlogN)的算法还是O(N^2),排序又有那几种常用算法呢?

排序算法我有总结了下:一般都用快速排序,堆排序,归并排序,插入排序,希尔排序,选择排序,冒泡排序等等

大家可以参见:http://blog.csdn.net/ylf13/article/details/12651117  我的这篇博文,不过还在补充中,内容不足还请谅解,其他算法大家可以再去了解了解

回到这题,需要时间复杂度O(n)看来是不能找出所有组合来得出结果了,但是我们发现,数据是排列好的,这就是说如果a[i]+a[j]>sum

假设a[i]>a[j],i 和j 分别是数组尾和数组头部两个Index,那么就需要i--如下(j++只会让结果更大)

2 4 6 8 9 10 16      15

j                     i

2 4 6 8 9 10 16      15

j                i

这时候发现2 + 10 < 15  所以j++

2 4 6 8 9 10 16      15

   j             i

4+10<15  j++

2 4 6 8 9 10 16      15

       j          i

 6+10>15  i--

2 4 6 8 9 10 16      15

       j     i

6+9 = 15  找到了!!

--------------------------

而且这个过程o(N)

问题再深度点,如果要找出所有和为15的呢?这就需要继续往下找,我给出了下面程序,同时避免输出同样的结果

例如 1 1 1 4       5

这样只输出1+4=5

//============================================================================
// Name        : FindSumFactor.cpp
// Author      : YLF
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
using namespace std;

#define MAX 50

void findFactor(int *arr, int num, int sum);

int main() {
	int arr[MAX];
	int input = 0;
	int num = -1;
	int sum = 0;

	while(true){
		num++;
		cin>>input;
		if(input == -1)
			break;
		else
			arr[num] = input;
	}

	sum = arr[--num];

	findFactor(arr, num, sum);
	return 0;
}

void findFactor(int *arr, int num, int sum){
	int i = num-1;
	int j = 0;

	int temp = -1;

	while(i > j){
		if(arr[i] + arr[j] > sum)
			i--;
		else if(arr[i] + arr[j] < sum)
			j++;
		else{
			if(temp == arr[j] || temp == arr[i]){
				//这个判断是去重复
				i--;
				continue;
			}
			cout<<arr[j]<<"+"<<arr[i]<<"="<<sum<<endl;
			temp = arr[i];
			i--;

		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值