Trouver 2 nombres dans un tableau non trié égal à une somme donnée

Nous avons besoin de trouver la paire de nombres dans un tableau dont la somme est égale à une valeur donnée.

A = {6,4,5,7,9,1,2}

Somme = 10 Alors les paires sont - {6,4} , {9,1}

j'ai deux solutions pour cela .

  • un O(nlogn) solution de tri + somme de contrôle avec 2 itérateurs (début et fin).
  • un O(n) solution - le hachage de la matrice. Puis vérifier si sum-hash[i] existe ou non dans la table de hachage.

mais, le problème est que, bien que la deuxième solution soit O(n) le temps , mais utilise O(N) l'espace aussi.

donc , je me demandais si nous pouvions le faire dans O(n) time et O(1) space. Et ce n'est PAS de devoirs!

47
demandé sur Devarshi 2012-03-11 20:38:33

18 réponses

utiliser radix sort en place et la première solution D'OP avec 2 itérateurs, venant l'un vers l'autre.

si les nombres dans le tableau ne sont pas une sorte de nombres de multi-précision et sont, par exemple, des entiers de 32 bits, vous pouvez les trier en 2*32 passes en utilisant pratiquement aucun espace supplémentaire (1 bit par passe). Soit 2 * 8 passes et 16 compteurs entiers (4 bits par passe).


détails pour la solution des 2 itérateurs:

le premier itérateur pointe d'abord vers le premier élément du tableau trié et avance. Deuxième itérateur pointe sur le dernier élément du tableau et les progrès vers l'arrière.

si la somme des éléments référencés par les itérateurs est inférieure à la valeur requise, avancer le premier itérateur. Si elle est supérieure à la valeur requise, avancez second itérateur. Si elle est égale à la valeur requise, le succès.

un seul le pass est nécessaire, donc la complexité temporelle est O (n). L'espace de la complexité est O(1). Si le tri radix est utilisé, les complexités de l'algorithme entier sont les mêmes.


si vous êtes intéressé par des problèmes apparentés (avec la somme de plus de 2 nombres), voir "Sum-subset with a fixed subset size" et "trouver trois éléments dans un tableau dont la somme est la plus proche d'un nombre donné" .

18
répondu Evgeny Kluev 2017-05-23 12:17:29

il s'agit d'une question d'entrevue classique de Microsoft research Asia.

Comment Trouver 2 nombres dans un tableau non trié égal à une somme donnée.

[1]solution de force brute

Cet algorithme est très simple. La complexité temporelle est O(N^2)

[2]Recherche binaire

En utilisant la recherche bianry pour trouver la somme-arr[i] avec chaque arr[i], la complexité du temps peut être réduite à O (N * logN)

[3]Utilisant Le Hash

En se basant sur l'algorithme [2] et en utilisant le hachage, la complexité temporelle peut être réduite à O(N), mais cette solution ajoutera l'espace O(N) du hachage.

[4]algorithme Optimal:

Pseduo-code:

for(i=0;j=n-1;i<j)
   if(arr[i]+arr[j]==sum) return (i,j);
else if(arr[i]+arr[j]<sum) i++;
else j--;
return(-1,-1);

ou

If a[M] + a[m] > I then M--
If a[M] + a[m] < I then m++
If a[M] + a[m] == I you have found it
If m > M, no such numbers exist.

et cette question est-elle résolue? Aucun. Si le nombre est N. ce problème deviendra très complexe.

la question alors:

Comment puis-je trouver tous les cas de combinaison avec un nombre donné?

il s'agit d'un NP classique-problème complet qui s'appelle sous-ensemble-somme.

Pour comprendre NP/NPC / NP-dur, vous feriez mieux de lire des livres professionnels.

, les Références:

[1] http://www.quora.com/Mathematics/How-can-I-find-all-the-combination-cases-with-a-given-number

[2] http://en.wikipedia.org/wiki/Subset_sum_problem

6
répondu Changqi Cai 2013-08-30 06:26:02
for (int i=0; i < array.size(); i++){
  int value = array[i];
  int diff = sum - value; 
  if (! hashSet.contains(diffvalue)){
      hashSet.put(value,value);
  } else{
       printf(sum = diffvalue + hashSet.get(diffvalue));
  } 
}

--------
Sum being sum of 2 numbers.
3
répondu Sandeep 2012-12-01 04:49:44

si vous supposez que la valeur M à laquelle les paires sont supposées additionner est constante et que les entrées dans le tableau sont positives, alors vous pouvez le faire en un passage ( O(n) time) en utilisant M/2 pointeurs ( O(1) space) comme suit. Les pointeurs sont étiquetés P1,P2,...,Pkk=floor(M/2) . Alors faites quelque chose comme ça

for (int i=0; i<N; ++i) {
  int j = array[i];
  if (j < M/2) {
    if (Pj == 0)
      Pj = -(i+1);   // found smaller unpaired
    else if (Pj > 0)
      print(Pj-1,i); // found a pair
      Pj = 0;
  } else
    if (Pj == 0)
      Pj = (i+1);    // found larger unpaired
    else if (Pj < 0)
      print(Pj-1,i); // found a pair
      Pj = 0;
  }
}

vous pouvez gérer les entrées répétées (par exemple deux 6's) en stockant les indices sous forme de chiffres dans la base N , par exemple. Pour M/2 , vous pouvez ajouter le conditionnel

  if (j == M/2) {
    if (Pj == 0)
      Pj = i+1;      // found unpaired middle
    else
      print(Pj-1,i); // found a pair
      Pj = 0;
  } 

Mais maintenant vous avez le problème de mettre les paires ensemble.

1
répondu PengOne 2012-03-11 17:17:14
    public void printPairsOfNumbers(int[] a, int sum){
    //O(n2)
    for (int i = 0; i < a.length; i++) {
        for (int j = i+1; j < a.length; j++) {
            if(sum - a[i] == a[j]){
                //match..
                System.out.println(a[i]+","+a[j]);
            }
        }
    }

    //O(n) time and O(n) space
    Set<Integer> cache = new HashSet<Integer>();
    cache.add(a[0]);
    for (int i = 1; i < a.length; i++) {
        if(cache.contains(sum - a[i])){
            //match//
            System.out.println(a[i]+","+(sum-a[i]));
        }else{
            cache.add(a[i]);
        }
    }

}
1
répondu Amandeep Dhanjal 2015-05-29 16:10:02

est-ce la solution la plus évidente de ne pas travailler (une itération sur chaque consécutives paire) ou sont les deux nombres dans n'importe quel ordre?

dans ce cas, vous pouvez trier la liste des nombres et utiliser l'échantillonnage aléatoire pour diviser la liste triée jusqu'à ce que vous ayez une sous-liste qui est assez petite pour être itérée plus.

0
répondu Blender 2012-03-11 16:48:17
public static ArrayList<Integer> find(int[] A , int target){
    HashSet<Integer> set = new HashSet<Integer>();
    ArrayList<Integer> list = new ArrayList<Integer>();
    int diffrence = 0;
    for(Integer i : A){
        set.add(i);
    }
    for(int i = 0; i <A.length; i++){
        diffrence = target- A[i];
    if(set.contains(diffrence)&&A[i]!=diffrence){
        list.add(A[i]);
        list.add(diffrence);
        return list;
    }
     }
    return null;
}
0
répondu Suraj 2013-08-30 05:56:06
`package algorithmsDesignAnalysis;

 public class USELESStemp {
 public static void main(String[] args){
    int A[] = {6, 8, 7, 5, 3, 11, 10}; 

    int sum = 12;
    int[] B = new int[A.length];
    int Max =A.length; 

    for(int i=0; i<A.length; i++){
        B[i] = sum - A[i];
        if(B[i] > Max)
            Max = B[i];
        if(A[i] > Max)
            Max = A[i];

        System.out.print(" " + B[i] + "");

    } // O(n) here; 

    System.out.println("\n Max = " + Max);

    int[] Array = new int[Max+1];
    for(int i=0; i<B.length; i++){
        Array[B[i]] = B[i];
    } // O(n) here;

    for(int i=0; i<A.length; i++){  
    if (Array[A[i]] >= 0)
        System.out.println("We got one: " + A[i] +" and " + (sum-A[i]));
    } // O(n) here;

} // end main();

/******
Running time: 3*O(n)
*******/
}
0
répondu todedu 2013-11-14 18:48:11

ci-dessous le code prend le tableau et le nombre N comme la somme cible. D'abord, le tableau est trié, puis un nouveau tableau contenant les les éléments restants sont pris et ensuite scannés pas par recherche binaire mais le balayage simple du reste et du tableau simultanément.

public static int solution(int[] a, int N) {

    quickSort(a, 0, a.length-1);    // nlog(n)

    int[] remainders = new int[a.length];

    for (int i=0; i<a.length; i++) {
        remainders[a.length-1-i] = N - a[i];     // n
    }

    int previous = 0;

    for (int j=0; j<a.length; j++) {            // ~~ n

        int k = previous;

        while(k < remainders.length && remainders[k] < a[j]) {
            k++;
        }

        if(k < remainders.length && remainders[k] == a[j]) {
            return 1;
        }

        previous = k;
    }

    return 0;
}
0
répondu user3264350 2014-02-03 03:14:25

ne devrait-il pas itérer des deux côtés pour résoudre le problème?

trier le tableau. Et de commencer la comparaison des deux extrémités.

if((arr[start] + arr[end]) < sum) start++;
if((arr[start] + arr[end]) > sum) end--;
if((arr[start] + arr[end]) = sum) {print arr[start] "," arr[end] ; start++}
if(start > end)  break;

Complexité Temporelle O(nlogn)

0
répondu Piyush Shandilya 2014-03-10 07:56:53

si c'est un trié tableau et nous n'avons besoin que de paires de nombres et pas toutes les paires nous pouvons le faire comme ceci:

public void sums(int a[] , int x){ // A = 1,2,3,9,11,20 x=11
    int i=0 , j=a.length-1;
    while(i < j){
      if(a[i] + a[j] == x) system.out.println("the numbers : "a[x] + " " + a[y]);
      else if(a[i] + a[j] < x) i++;
      else j--;
    }
}

1 2 3 9 11 20 || i=0 , j = 5 somme = 21 x=11

1 2 3 9 11 20 || i=0 , j = 4 somme = 13 x=11

1 2 3 9 11 20 || i=0 , j = 4 somme=11 x=11

Fin

0
répondu igor 2014-05-30 17:33:48

le code suivant renvoie true si deux entiers dans un tableau correspondent à un entier comparé.

 function compareArraySums(array, compare){

        var candidates = [];

        function compareAdditions(element, index, array){
            if(element <= y){
                candidates.push(element);
            }
        }

        array.forEach(compareAdditions);

        for(var i = 0; i < candidates.length; i++){
            for(var j = 0; j < candidates.length; j++){
                if (i + j === y){
                    return true;
                }
            }
        }
    }
0
répondu redress 2015-05-22 22:34:19

Python 2.7 Mise En Œuvre:

import itertools
list = [1, 1, 2, 3, 4, 5,]
uniquelist = set(list)
targetsum = 5
for n in itertools.combinations(uniquelist, 2):
    if n[0] + n[1] == targetsum:
    print str(n[0]) + " + " + str(n[1])

sortie:

1 + 4
2 + 3
0
répondu Erict2k 2015-12-07 03:54:19

https://github.com/clockzhong/findSumPairNumber

#! /usr/bin/env python
import sys
import os
import re


#get the number list
numberListStr=raw_input("Please input your number list (seperated by spaces)...\n")
numberList=[int(i) for i in numberListStr.split()]
print 'you have input the following number list:'
print numberList

#get the sum target value
sumTargetStr=raw_input("Please input your target number:\n")
sumTarget=int(sumTargetStr)
print 'your target is: '
print sumTarget


def generatePairsWith2IndexLists(list1, list2):
    result=[]
    for item1 in list1:
        for item2 in list2:
            #result.append([item1, item2])
            result.append([item1+1, item2+1])
    #print result
    return result

def generatePairsWithOneIndexLists(list1):
    result=[]
    index = 0
    while index< (len(list1)-1):
        index2=index+1
        while index2 < len(list1):
            #result.append([list1[index],list1[index2]])
            result.append([list1[index]+1,list1[index2]+1])
            index2+=1
        index+=1
    return result


def getPairs(numList, target):
    pairList=[]
    candidateSlots=[] ##we have (target-1) slots 

    #init the candidateSlots list
    index=0
    while index < target+1:
        candidateSlots.append(None)
        index+=1

    #generate the candidateSlots, contribute O(n) complexity
    index=0
    while index<len(numList):
        if numList[index]<=target and numList[index]>=0:
            #print 'index:',index
            #print 'numList[index]:',numList[index]     
            #print 'len(candidateSlots):',len(candidateSlots)
            if candidateSlots[numList[index]]==None:
                candidateSlots[numList[index]]=[index]
            else:
                candidateSlots[numList[index]].append(index)
        index+=1

    #print candidateSlots

    #generate the pairs list based on the candidateSlots[] we just created
    #contribute O(target) complexity
    index=0
    while index<=(target/2):
        if candidateSlots[index]!=None and candidateSlots[target-index]!=None:
            if index!=(target-index):
                newPairList=generatePairsWith2IndexLists(candidateSlots[index], candidateSlots[target-index])
            else:
                newPairList=generatePairsWithOneIndexLists(candidateSlots[index])
            pairList+=newPairList
        index+=1

    return pairList

print getPairs(numberList, sumTarget)

j'ai implémenté avec succès une solution avec Python sous O(n+m) time and space cost. Le" m " est la valeur cible à laquelle la somme de ces deux nombres doit être égale. Je crois que c'est le coût le plus bas possible. Erict2k utilise des outils itératifs.les combinaisons, il en coûtera également similaire ou plus de temps et d'espace coût de comparer mon algorithme.

0
répondu Clock ZHONG 2016-04-01 08:45:13

si les nombres ne sont pas très grands, vous pouvez utiliser la Transformée de fourier rapide pour multiplier deux polynômes et puis dans O(1) vérifier si le coefficient avant x^(somme nécessaire) somme est plus que zéro. O(n log n) total de la!

0
répondu alkurmtl 2016-11-10 15:38:40

// Java mise en œuvre à l'aide de Hachage importer java.io.*;

classe PairSum { private static final int MAX = 100000; / / Max size of Hashmap

static void printpairs(int arr[],int sum)
{
    // Declares and initializes the whole array as false
    boolean[] binmap = new boolean[MAX];

    for (int i=0; i<arr.length; ++i)
    {
        int temp = sum-arr[i];

        // checking for condition
        if (temp>=0 && binmap[temp])
        {
            System.out.println("Pair with given sum " +
                                sum + " is (" + arr[i] +
                                ", "+temp+")");
        }
        binmap[arr[i]] = true;
    }
}

// Main to test the above function
public static void main (String[] args)
{
    int A[] = {1, 4, 45, 6, 10, 8};
    int n = 16;
    printpairs(A,  n);
}

}

0
répondu Sai kiran 2017-06-21 07:38:17

créer un dictionnaire avec la clé de paires (nombre de la liste) et la valeur est le nombre qui est nécessaire pour obtenir une valeur désirée. Ensuite, vérifiez la présence des paires de nombres dans la liste.

def check_sum_in_list(p_list, p_check_sum):
    l_dict = {i: (p_check_sum - i) for i in p_list}
    for key, value in l_dict.items():
        if key in p_list and value in p_list:
            return True
    return False


if __name__ == '__main__':
    l1 = [1, 3, 7, 12, 72, 2, 8]
    l2 = [1, 2, 2, 4, 7, 4, 13, 32]

    print(check_sum_in_list(l1, 10))
    print(check_sum_in_list(l2, 99))

Output:
True
Flase

version 2

import random


def check_sum_in_list(p_list, p_searched_sum):
    print(list(p_list))
    l_dict = {i: p_searched_sum - i for i in set(p_list)}
    for key, value in l_dict.items():
        if key in p_list and value in p_list:
            if p_list.index(key) != p_list.index(value):
                print(key, value)
                return True
    return False


if __name__ == '__main__':
    l1 = []
    for i in range(1, 2000000):
        l1.append(random.randrange(1, 1000))

    j = 0
    i = 9
    while i < len(l1):
        if check_sum_in_list(l1[j:i], 100):
            print('Found')
            break
        else:
            print('Continue searching')
            j = i
            i = i + 10

Output:
...
[154, 596, 758, 924, 797, 379, 731, 278, 992, 167]
Continue searching
[808, 730, 216, 15, 261, 149, 65, 386, 670, 770]
Continue searching
[961, 632, 39, 888, 61, 18, 166, 167, 474, 108]
39 61
Finded
[Finished in 3.9s]
0
répondu Howl Blindfolds 2018-01-25 21:32:41
    public static void Main(string[] args)
    {
        int[] myArray =  {1,2,3,4,5,6,1,4,2,2,7 };
        int Sum = 9;

            for (int j = 1; j < myArray.Length; j++)
            {                    
                if (myArray[j-1]+myArray[j]==Sum)
                {
                    Console.WriteLine("{0}, {1}",myArray[j-1],myArray[j]);
                }
            }            
        Console.ReadLine();
    }
-1
répondu yitbarek 2017-04-14 08:31:25