编程之美--快速寻找满足条件的两个数

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

1.     直接穷举,从数组中任意选取两个数,判定它们的和是否为输入的那个数字。此举复杂度为ON^2)。很显然,我们要寻找效率更高的解法。

2.     题目相当于,对每个a[i],然后查找判断sum-a[i]是否也在原始序列中,每一次要查找的时间都要花费为ON),这样下来,最终找到两个数还是需要ON^2)的复杂度。那如何提高查找判断的速度列?对了,二分查找,将原来ON)的查找时间提高到OlogN),这样对于Na[i],都要花logN的时间去查找相对应的sum-a[i]是否在原始序列中,总的时间复杂度已降为ON*logN),且空间复杂度为O1)。(如果有序,直接二分ON*logN),如果无序,先排序后二分,复杂度同样为ON*logN+N*logN=ON*logN),空间总为O1))。

3.     有没有更好的办法列?咱们可以依据上述思路2的思想,a[i]在序列中,如果a[i]+a[k]=sum的话,那么sum-a[i]a[k])也必然在序列中,,举个例子,如下:
原始序列:1 2 4 71115    用输入数字15减一下各个数,得到对应的序列为:
对应序列:14131184 0      
第一个数组以一指针i从数组最左端开始向右扫描,第二个数组以一指针j从数组最右端开始向左扫描,如果下面出现了和上面一样的数,即a[*i]=a[*j],就找出这俩个数来了。如上,ij最终在第一个,和第二个序列中找到了相同的数411,,所以符合条件的两个数,即为4+11=15。如果数组是无序的,先排序(n*logn),然后用两个指针ij,各自指向数组的首尾两端,令i=0j=n-1,然后i++j--,逐次判断a[i]+a[j]?=sum,如果某一刻a[i]+a[j]>sum,则要想办法让sum的值减小,所以此刻i不动,j--,如果某一刻a[i]+a[j]<sum,则要想办法让sum的值增大,所以此刻i++j不动。所以,数组无序的时候,时间复杂度最终为On*logn+n=On*logn),若原数组是有序的,则不需要事先的排序,直接On)搞定,且空间复杂度还是O1),此思路是相对于上述所有思路的一种改进。(如果有序,直接两个指针两端扫描,时间ON),如果无序,先排序后两端扫描,时间ON*logN+N=ON*logN),空间始终都为O1))。(与上述思路2相比,排序后的时间开销由之前的二分的n*logn降到了扫描的ON)。

4.     不论原序列是有序还是无序,解决这类题有以下三种办法:1、二分(若无序,先排序后二分),时间复杂度总为On*logn),空间复杂度为O1);2、扫描一遍X-S[i] 映射到一个数组或构造hash表,时间复杂度为On),空间复杂度为On);3、两个指针两端扫描(若无序,先排序后扫描),时间复杂度最后为:有序On),无序On*logn+n=On*logn),空间复杂度都为O1

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值