寻找和为定值的两个数

Posted 泡面小王子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寻找和为定值的两个数相关的知识,希望对你有一定的参考价值。

 

1. 题目描述

 

    给定一个数组(无序或者有序,两种情况都要考虑),找出和为M的两个数。最多时间复杂度能有多少?

    https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/02.02.md

 

2. 数组有序——两端指针扫描法

 

    数组有序的情况,在时间复杂度上我们就省去了排序的O(NlogN)。

    我们使用两端指针扫描法是比较简单的,时间复杂度为O(N), 空间复杂度为O(1)。如下图所示:

技术分享

 

首先我们在数组两端分别放上一个标志:head, tail。

然后,判断它们指向的值之和sum是否等于M,

               如果sum==M, 记录结果!head, tail同时往中间移动一次;

               如果sum<M, tail往中间移动一次;

               如果sum>M, head往中间移动。

直到,head>tail,返回结果~

 

总共的时间复杂度就是很厉害的O(N), 空间复杂度也只是O(1)。但是注意前提是数组要有序~

 

程序如下:

 

 

3. 数组无序——映射hash表或者数组

 

    当数组无序的时候,当时我们可以先排序, 然后再使用上面的方法。这是时间复杂度为O(NlogN),空间复杂度为O(1)。

 

    或者我们还可以使用映射hash表或者数组,详细来说:

把数组M - a[i]映射到一个hash表或者是一个数组,然后我们就判断原数组和数组M - a[i]时候有元素相等,如果则返回结果。判断相等的方法我们也可以使用两端夹逼方法。

 

技术分享

 

这种方法的时间复杂度为O(N), 空间复杂度为O(N)。

ps:其实在无序的情况,还是映射到hash表比较好,映射到数组也不是很好操作~

#include <iostream>
using namespace std;
const int size=100;

int main()
{
    int hashtable[size];
    for(int i=0;i<size;i++)
        hashtable[i]=0;
    int a[size]={1,2,4,5,7,11,15};
    for(int i=0;i<7;i++)
        hashtable[a[i]]=1;
    int sum=15;
    for(int i=0;i<7;i++)
        if(hashtable[i]&&hashtable[sum-i])
          cout<<"这两个数为"<<i<<" "<<sum-i<<endl;
        else
          cout<<"不存在这样的两个数."<<endl;
    return 0;
}

 

以上是关于寻找和为定值的两个数的主要内容,如果未能解决你的问题,请参考以下文章

编程之法section II: 2.2 和为定值的两个数

和为定值的两个数

编程之法:面试和算法心得(寻找和为定值的多个数)

和为定值的多个数

和为定值的m个数

使用java,列举所有给定数组中和为定值的组合