Trouver une paire d'éléments dans un tableau dont la somme est égale à un nombre donné


122

Étant donné un tableau de n entiers et un nombre X donné, trouvez toutes les paires uniques d'éléments (a, b), dont la sommation est égale à X.

Ce qui suit est ma solution, c'est O (nLog (n) + n), mais je ne sais pas si elle est optimale ou non.

int main(void)
{
    int arr [10] = {1,2,3,4,5,6,7,8,9,0};
    findpair(arr, 10, 7);
}
void findpair(int arr[], int len, int sum)
{
    std::sort(arr, arr+len);
    int i = 0;
    int j = len -1;
    while( i < j){
        while((arr[i] + arr[j]) <= sum && i < j)
        {
            if((arr[i] + arr[j]) == sum)
                cout << "(" << arr[i] << "," << arr[j] << ")" << endl;
            i++;
        }
        j--;
        while((arr[i] + arr[j]) >= sum && i < j)
        {
            if((arr[i] + arr[j]) == sum)
                cout << "(" << arr[i] << "," << arr[j] << ")" << endl;
            j--;
        }
    }
}

3
Une solution O (n) est possible si vous jetez tout dans un ensemble O (1) quelconque au lieu de trier le tableau.
Anon.

1
@Anon Pouvez-vous dire plus de détails, comment construire un tel ensemble?
Gin

3
Utilisez des hachages. La plupart des langages auront un HashSet O (1) amorti quelque part dans leurs bibliothèques standard.
Anon.

15
Un nit mineur - O (nLog (n) + n) est O (nLog (n)). La notation Big O ne conserve que le terme dominant et supprime tous les termes d'ordre inférieur.
pjs

2
Notez l'évaluation des courts-circuits et l'adressage un par un: while((arr[i] + arr[j]) <= sum && i < j)devrait être while( i < J && arr[i] + arr[j] <= sum ). (similaire pour la deuxième sous-boucle)
wildplasser

Réponses:


135
# Let arr be the given array.
# And K be the give sum


for i=0 to arr.length - 1 do
  hash(arr[i]) = i  // key is the element and value is its index.
end-for

for i=0 to arr.length - 1 do
  if hash(K - arr[i]) != i  // if Kth element exists and it's different then we found a pair
    print "pair i , hash(K - arr[i]) has sum K"
  end-if
end-for

26
Vous pouvez même le faire en une itération dans le tableau, en plaçant votre instruction if de la deuxième boucle, juste après l'affectation de hachage dans la première boucle.
Alexander Kondratskiy

4
Note mineure: Ceci (ainsi que la suggestion d'Alexandre) imprimera en double certaines paires, que l'unicité d'une paire soit déterminée par l'indice (comme cela pourrait être impliqué dans cette réponse) ou par la valeur (comme cela semble dans l'OP). Il pourrait y avoir un certain nombre de paires uniques (O (n ^ 2)) par index, par exemple arr=[1,2,1,2,1,2,1,...]. Pour l'unicité par valeur, il semble qu'une autre table de hachage indexée par une paire de valeurs ferait l'affaire. Encore une réponse agréable, compacte et élégante. +1
William

2
@codaddict Mais que faire si le tableau est très grand? Je veux dire que la plage de valeurs est très large? Ainsi, la solution de hachage sera alors moins pratique. Une méthode alternative et optimale pour la même chose?
Prashant Singh

15
Et s'il y a des doublons?
zad le

2
hash(K - arr[i]) != iVérifie- t-il en quelque sorte à la fois la présence et l'absence de correspondance? Je m'attendrais à ce qu'il y ait un contrôle de présence séparé.
Joseph Garvin

184

Il existe 3 approches pour cette solution:

Soit la somme T et n la taille du tableau

Approche 1:
La manière naïve de procéder serait de vérifier toutes les combinaisons (n ​​choisissez 2). Cette recherche exhaustive est O (n 2 ).

Approche 2: 
 Une meilleure façon serait de trier le tableau. Cela prend O (n log n)
Ensuite, pour chaque x du tableau A, utilisez la recherche binaire pour rechercher Tx. Cela prendra O (nlogn).
Donc, la recherche globale est O (n log n)

Approche 3:
La meilleure façon serait d'insérer chaque élément dans une table de hachage (sans tri). Cela prend O (n) comme insertion à temps constant.
Ensuite, pour chaque x, nous pouvons simplement rechercher son complément, Tx, qui est O (1).
Globalement, le temps d'exécution de cette approche est O (n).


Vous pouvez en référer plus ici .Merci.



Comment créeriez-vous une table de hachage pour les éléments du tableau?
Satish Patel

Reportez-vous au lien que j'ai partagé. Nous pouvons avoir un tableau parallèle pour stocker l'élément en tant qu'index, ou vous pouvez ajouter les éléments à la table de hachage et utiliser contient sur eux. Désolé pour une réponse aussi tardive.
kinshuk4

11
Vous pourriez obtenir un faux positif s'il y a un élément qui est exactement la moitié de la somme cible.
Florian F

2
@Florian_F Ne pouvez-vous pas juste un cas particulier où vous avez un élément exactement la moitié?
Joseph Garvin

1
@jazzz Je veux dire HashMap ici, bien que HashSet le fasse également. Voici l'implémentation - github.com/kinshuk4/AlgorithmUtil/blob/master/src/com/vaani/… . J'espère que ça aide.
kinshuk4

64

Implémentation en Java: Utilisation de l'algorithme de codaddict (Peut-être légèrement différent)

import java.util.HashMap;

public class ArrayPairSum {


public static void main(String[] args) {        

    int []a = {2,45,7,3,5,1,8,9};
    printSumPairs(a,10);        

}


public static void printSumPairs(int []input, int k){
    Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();

    for(int i=0;i<input.length;i++){

        if(pairs.containsKey(input[i]))
            System.out.println(input[i] +", "+ pairs.get(input[i]));
        else
            pairs.put(k-input[i], input[i]);
    }

}
}

Pour input = {2,45,7,3,5,1,8,9}et si Sum est10

Paires de sortie:

3,7 
8,2
9,1

Quelques notes sur la solution:

  • Nous n'itérons qu'une seule fois dans le tableau -> O (n) temps
  • Le temps d'insertion et de recherche dans Hash est O (1).
  • Le temps global est O (n), bien qu'il utilise un espace supplémentaire en termes de hachage.

1
C'est bon UNIQUEMENT si le tableau d'entrée n'a pas de doublons.
Naren

2
@Naren: Cela ne fait aucune différence même s'il y a des doublons dans le tableau donné
abhishek08aug

1
il n'implémente pas ce que codaddicts a écrit, et ce que vous avez fait, bien que cela fonctionne, n'est pas compliqué. Cela n'a pas de sens de put(k-input[i], input[i])(codaddicts met l'index comme valeur, ce qui est utile.) Ce que vous avez écrit peut être simplifié enfor (i:input){ if (intSet.contains(sum-i) { print(i + "," + (sum-i) ); } else {intSet.add(i)}
Adrian Shum

1
D'accord merci. Pour d'autres fins de référence, je viens de créer un autre fil de discussion afin que ceux qui ont des difficultés à analyser le fonctionnement de cette solution puissent le comprendre correctement. Voici le lien: stackoverflow.com/questions/33274952/…
John

2
@ abhishek08aug cela ne fonctionnera pas pendant {1, 1, 1}
jbakirov

8

Solution en java. Vous pouvez ajouter tous les éléments String à un ArrayList de chaînes et renvoyer la liste. Ici, je suis juste en train de l'imprimer.

void numberPairsForSum(int[] array, int sum) {
    HashSet<Integer> set = new HashSet<Integer>();
    for (int num : array) {
        if (set.contains(sum - num)) {
            String s = num + ", " + (sum - num) + " add up to " + sum;
            System.out.println(s);
        }
        set.add(num);
    }
}

4

Implémentation Python:

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])

Production:

1 + 4
2 + 3

2
regarder dans ... sera au-dessus pour l'élément de recherche
Nikhil Rupanawar

4

C ++ 11, complexité d'exécution O (n):

#include <vector>
#include <unordered_map>
#include <utility>

std::vector<std::pair<int, int>> FindPairsForSum(
        const std::vector<int>& data, const int& sum)
{
    std::unordered_map<int, size_t> umap;
    std::vector<std::pair<int, int>> result;
    for (size_t i = 0; i < data.size(); ++i)
    {
        if (0 < umap.count(sum - data[i]))
        {
            size_t j = umap[sum - data[i]];
            result.push_back({data[i], data[j]});
        }
        else
        {
            umap[data[i]] = i;
        }
    }

    return result;
}

3

Voici une solution qui prend en compte les doublons. Il est écrit en javascript et suppose que le tableau est trié. La solution s'exécute en temps O (n) et n'utilise aucune mémoire supplémentaire en dehors de la variable.

var count_pairs = function(_arr,x) {
  if(!x) x = 0;
  var pairs = 0;
  var i = 0;
  var k = _arr.length-1;
  if((k+1)<2) return pairs;
  var halfX = x/2; 
  while(i<k) {
    var curK = _arr[k];
    var curI = _arr[i];
    var pairsThisLoop = 0;
    if(curK+curI==x) {
      // if midpoint and equal find combinations
      if(curK==curI) {
        var comb = 1;
        while(--k>=i) pairs+=(comb++);
        break;
      }
      // count pair and k duplicates
      pairsThisLoop++;
      while(_arr[--k]==curK) pairsThisLoop++;
      // add k side pairs to running total for every i side pair found
      pairs+=pairsThisLoop;
      while(_arr[++i]==curI) pairs+=pairsThisLoop;
    } else {
      // if we are at a mid point
      if(curK==curI) break;
      var distK = Math.abs(halfX-curK);
      var distI = Math.abs(halfX-curI);
      if(distI > distK) while(_arr[++i]==curI);
      else while(_arr[--k]==curK);
    }
  }
  return pairs;
}

J'ai résolu ce problème lors d'une interview pour une grande entreprise. Ils l'ont pris mais pas moi. Alors voilà pour tout le monde.

Commencez des deux côtés de la matrice et avancez lentement vers l'intérieur en vous assurant de compter les doublons s'ils existent.

Il ne compte que les paires mais peut être retravaillé pour

  • trouve les paires
  • trouver des paires <x
  • trouver des paires> x

Prendre plaisir!


Que font ces lignes ?: if(distI > distK) while(_arr[++i]==curI); else while(_arr[--k]==curK);
Yuriy Chernyshov

Ces lignes ignorent les valeurs en double de chaque côté et les comptent comme des paires si elles font partie d'une paire somme = N
Drone Brain

3

Sur)

def find_pairs(L,sum):
    s = set(L)
    edgeCase = sum/2
    if L.count(edgeCase) ==2:
        print edgeCase, edgeCase
    s.remove(edgeCase)      
    for i in s:
        diff = sum-i
        if diff in s: 
            print i, diff


L = [2,45,7,3,5,1,8,9]
sum = 10          
find_pairs(L,sum)

Méthodologie: a + b = c, donc au lieu de chercher (a, b) on cherche a = c - b


Ne fonctionne pas si vous avez des doublons dans l'entrée, comme ceci: [3, 4, 3, 2, 5] et somme = 6
Anton Danilchenko

Correction de tous les cas
extrêmes

2

Implémentation en Java: Utilisation de l'algorithme de codaddict:

import java.util.Hashtable;
public class Range {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Hashtable mapping = new Hashtable();
    int a[]= {80,79,82,81,84,83,85};
    int k = 160;

    for (int i=0; i < a.length; i++){
        mapping.put(a[i], i);
    }

    for (int i=0; i < a.length; i++){
        if (mapping.containsKey(k - a[i]) && (Integer)mapping.get(k-a[i]) != i){
            System.out.println(k-a[i]+", "+ a[i]);
        }
    }      

}

}

Production:

81, 79
79, 81

Si vous voulez des paires dupliquées (par exemple: 80,80), supprimez simplement && (Integer) mapping.get (ka [i])! = I de la condition if et vous êtes prêt à partir.


pour C # cela peut être work - int k = 16; nombre int = 0; int [] intArray = {5, 7, 11, 23,8,9,15,1,10,6}; for (int i = 0; i <intArray.Length; i ++) {for (int j = i; j <intArray.Length; j ++) {if ((k - intArray [i]) == intArray [j]) { count ++; }}} Console.WriteLine (nombre);
MukulSharma

2

Je viens de participer à cette question sur HackerRank et voici ma solution `` Objectif C '' :

-(NSNumber*)sum:(NSArray*) a andK:(NSNumber*)k {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    long long count = 0;
    for(long i=0;i<a.count;i++){

        if(dict[a[i]]) {
            count++;
            NSLog(@"a[i]: %@, dict[array[i]]: %@", a[i], dict[a[i]]);
        }
        else{
            NSNumber *calcNum = @(k.longLongValue-((NSNumber*)a[i]).longLongValue);
            dict[calcNum] = a[i];
        }

    }
    return @(count);
}

J'espère que ça aide quelqu'un.


la syntaxe du code est difficile à comprendre que l'algorithme lui-même! :)
Rajendra Uppal

1

c'est l'implémentation de O (n * lg n) utilisant l'implémentation de la recherche binaire dans une boucle.

#include <iostream>

using namespace std;

bool *inMemory;


int pairSum(int arr[], int n, int k)
{
    int count = 0;

    if(n==0)
        return count;
    for (int i = 0; i < n; ++i)
    {
        int start = 0;
        int end = n-1;      
        while(start <= end)
        {
            int mid = start + (end-start)/2;
            if(i == mid)
                break;
            else if((arr[i] + arr[mid]) == k && !inMemory[i] && !inMemory[mid])
            {
                count++;
                inMemory[i] = true;
                inMemory[mid] = true;
            }
            else if(arr[i] + arr[mid] >= k)
            {
                end = mid-1;
            }
            else
                start = mid+1;
        }
    }
    return count;
}


int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    inMemory = new bool[10];
    for (int i = 0; i < 10; ++i)
    {
        inMemory[i] = false;
    }
    cout << pairSum(arr, 10, 11) << endl;
    return 0;
}

1

En python

arr = [1, 2, 4, 6, 10]
diff_hash = {}
expected_sum = 3
for i in arr:
    if diff_hash.has_key(i):
        print i, diff_hash[i]
    key = expected_sum - i
    diff_hash[key] = i

1

Belle solution de Codeaddict. J'ai pris la liberté d'en implémenter une version en Ruby:

def find_sum(arr,sum)
 result ={}
 h = Hash[arr.map {|i| [i,i]}]
 arr.each { |l| result[l] = sum-l  if h[sum-l] && !result[sum-l]  }
 result
end

Pour autoriser les doublons (1,5), (5,1), il suffit de supprimer l' && !result[sum-l]instruction


1

Voici le code Java pour trois approches:
1. En utilisant Map O (n), HashSet peut également être utilisé ici.
2. Triez le tableau et utilisez BinarySearch pour rechercher le complément O (nLog (n))
3. BruteForce traditionnel à deux boucles O (n ^ 2)

public class PairsEqualToSum {

public static void main(String[] args) {
    int a[] = {1,10,5,8,2,12,6,4};
    findPairs1(a,10);
    findPairs2(a,10);
    findPairs3(a,10);

}


//Method1 - O(N) use a Map to insert values as keys & check for number's complement in map
    static void findPairs1(int[]a, int sum){
        Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();
        for(int i=0; i<a.length; i++){
            if(pairs.containsKey(sum-a[i]))
                System.out.println("("+a[i]+","+(sum-a[i])+")");
            else
               pairs.put(a[i], 0);
        }
    }



//Method2 - O(nlog(n)) using Sort
static void findPairs2(int[]a, int sum){
        Arrays.sort(a);
        for(int i=0; i<a.length/2; i++){
            int complement = sum - a[i];
            int foundAtIndex = Arrays.binarySearch(a,complement);
            if(foundAtIndex >0 && foundAtIndex != i) //to avoid situation where binarySearch would find the original and not the complement like "5"
                System.out.println("("+a[i]+","+(sum-a[i])+")");
        }
 }

//Method 3 - Brute Force O(n^2)
static void findPairs3(int[]a, int sum){

    for(int i=0; i<a.length; i++){
        for(int j=i; j<a.length;j++){
            if(a[i]+a[j] == sum)
                System.out.println("("+a[i]+","+a[j]+")");
        }
    }
}

}

1

Un programme simple en java pour les tableaux ayant des éléments uniques:

import java.util.*;
public class ArrayPairSum {
    public static void main(String[] args) { 
        int []a = {2,4,7,3,5,1,8,9,5};
        sumPairs(a,10);  
    }

    public static void sumPairs(int []input, int k){
      Set<Integer> set = new HashSet<Integer>();    
      for(int i=0;i<input.length;i++){

        if(set.contains(input[i]))
            System.out.println(input[i] +", "+(k-input[i]));
        else
            set.add(k-input[i]);
       }
    }
}

1

Un simple extrait de code Java pour imprimer les paires ci-dessous:

    public static void count_all_pairs_with_given_sum(int arr[], int S){
        if(arr.length < 2){
        return;
    }        
    HashSet values = new HashSet(arr.length);
    for(int value : arr)values.add(value);
    for(int value : arr){
        int difference = S - value;
    if(values.contains(difference) && value<difference){
        System.out.printf("(%d, %d) %n", value, difference);
        }
    }
    }

1

Une autre solution dans Swift: l'idée est de créer un hachage qui stocke les valeurs de (sum - currentValue) et de le comparer à la valeur actuelle de la boucle. La complexité est O (n).

func findPair(list: [Int], _ sum: Int) -> [(Int, Int)]? {
    var hash = Set<Int>() //save list of value of sum - item.
    var dictCount = [Int: Int]() //to avoid the case A*2 = sum where we have only one A in the array
    var foundKeys  = Set<Int>() //to avoid duplicated pair in the result.

    var result = [(Int, Int)]() //this is for the result.
    for item in list {

        //keep track of count of each element to avoid problem: [2, 3, 5], 10 -> result = (5,5)
        if (!dictCount.keys.contains(item)) {
            dictCount[item] = 1
        } else {
            dictCount[item] = dictCount[item]! + 1
        }

        //if my hash does not contain the (sum - item) value -> insert to hash.
        if !hash.contains(sum-item) {
            hash.insert(sum-item)
        }

        //check if current item is the same as another hash value or not, if yes, return the tuple.
        if hash.contains(item) &&
            (dictCount[item] > 1 || sum != item*2) // check if we have item*2 = sum or not.
        {
            if !foundKeys.contains(item) && !foundKeys.contains(sum-item) {
                foundKeys.insert(item) //add to found items in order to not to add duplicated pair.
                result.append((item, sum-item))
            }
        }
    }
    return result
}

//test:
let a = findPair([2,3,5,4,1,7,6,8,9,5,3,3,3,3,3,3,3,3,3], 14) //will return (8,6) and (9,5)

1

Ma solution - Java - Sans doublons

    public static void printAllPairSum(int[] a, int x){
    System.out.printf("printAllPairSum(%s,%d)\n", Arrays.toString(a),x);
    if(a==null||a.length==0){
        return;
    }
    int length = a.length;
    Map<Integer,Integer> reverseMapOfArray = new HashMap<>(length,1.0f);
    for (int i = 0; i < length; i++) {
        reverseMapOfArray.put(a[i], i);
    }

    for (int i = 0; i < length; i++) {
        Integer j = reverseMapOfArray.get(x - a[i]);
        if(j!=null && i<j){
            System.out.printf("a[%d] + a[%d] = %d + %d = %d\n",i,j,a[i],a[j],x);
        }
    }
    System.out.println("------------------------------");
}

0

Cela imprime les paires et évite les doublons en utilisant la manipulation au niveau du bit.

public static void findSumHashMap(int[] arr, int key) {
    Map<Integer, Integer> valMap = new HashMap<Integer, Integer>();
    for(int i=0;i<arr.length;i++)
        valMap.put(arr[i], i);

    int indicesVisited = 0; 
    for(int i=0;i<arr.length;i++) {
        if(valMap.containsKey(key - arr[i]) && valMap.get(key - arr[i]) != i) {
            if(!((indicesVisited & ((1<<i) | (1<<valMap.get(key - arr[i])))) > 0)) {
                int diff = key-arr[i];
                System.out.println(arr[i] + " " +diff);
                indicesVisited = indicesVisited | (1<<i) | (1<<valMap.get(key - arr[i]));
            }
        }
    }
}

0

J'ai contourné la manipulation des bits et j'ai juste comparé les valeurs d'index. C'est moins que la valeur d'itération de la boucle (i dans ce cas). Cela n'imprimera pas les paires en double et les éléments du tableau en double également.

public static void findSumHashMap(int[] arr, int key) {
    Map<Integer, Integer> valMap = new HashMap<Integer, Integer>();
    for (int i = 0; i < arr.length; i++) {
        valMap.put(arr[i], i);
    }
    for (int i = 0; i < arr.length; i++) {
        if (valMap.containsKey(key - arr[i])
                && valMap.get(key - arr[i]) != i) {
            if (valMap.get(key - arr[i]) < i) {
                int diff = key - arr[i];
                System.out.println(arr[i] + " " + diff);
            }
        }
    }
}

0

en C #:

        int[] array = new int[] { 1, 5, 7, 2, 9, 8, 4, 3, 6 }; // given array
        int sum = 10; // given sum
        for (int i = 0; i <= array.Count() - 1; i++)
            if (array.Contains(sum - array[i]))
                Console.WriteLine("{0}, {1}", array[i], sum - array[i]);

cette réponse serait plus utile si vous décrivez l'ordre de croissance de votre solution
Thomas

0

Une solution peut être celle-ci, mais pas optimul (la complexité de ce code est O (n ^ 2)):

public class FindPairsEqualToSum {

private static int inputSum = 0;

public static List<String> findPairsForSum(int[] inputArray, int sum) {
    List<String> list = new ArrayList<String>();
    List<Integer> inputList = new ArrayList<Integer>();
    for (int i : inputArray) {
        inputList.add(i);
    }
    for (int i : inputArray) {
        int tempInt = sum - i;
        if (inputList.contains(tempInt)) {
            String pair = String.valueOf(i + ", " + tempInt);
            list.add(pair);
        }
    }
    return list;
   }
}

0

Une version python simple du code qui trouve une somme de paires de zéro et peut être modifiée pour trouver k:

def sumToK(lst):
    k = 0  # <- define the k here
    d = {} # build a dictionary 

# build the hashmap key = val of lst, value = i
for index, val in enumerate(lst):
    d[val] = index

# find the key; if a key is in the dict, and not the same index as the current key
for i, val in enumerate(lst):
    if (k-val) in d and d[k-val] != i:
        return True

return False

La complexité d'exécution de la fonction est également O (n) et Space: O (n).


0
 public static int[] f (final int[] nums, int target) {
    int[] r = new int[2];
    r[0] = -1;
    r[1] = -1;
    int[] vIndex = new int[0Xfff];
    for (int i = 0; i < nums.length; i++) {
        int delta = 0Xff;
        int gapIndex = target - nums[i] + delta;
        if (vIndex[gapIndex] != 0) {
            r[0] = vIndex[gapIndex];
            r[1] = i + 1;
            return r;
        } else {
            vIndex[nums[i] + delta] = i + 1;
        }
    }
    return r;
}

0

la solution inférieure à o (n) sera =>

function(array,k)
          var map = {};
          for element in array
             map(element) = true;
             if(map(k-element)) 
                 return {k,element}

Échouera pour certaines entrées. De plus, vous deviez retourner une somme non parisienne
Aviad

0

Solution en Python utilisant la compréhension de liste

f= [[i,j] for i in list for j in list if j+i==X];

O (N 2 )

donne également deux paires ordonnées - (a, b) et (b, a)


Vous pouvez mentionner une langue, si les paires (a, b) et (b, a) sont uniques, et à quelle question elle répond (la question ne contient pas de question explicite - I am not sure … Thanks for comments). Vous pourriez désigner le coup de pinceau à la complexité plus proche de O (n²).
greybeard

0

Je peux le faire en O (n). Faites-moi savoir quand vous voulez la réponse. Notez qu'il s'agit simplement de parcourir le tableau une fois sans tri, etc ... Je dois également mentionner qu'il exploite la commutativité de l'addition et n'utilise pas de hachage mais gaspille de la mémoire.


en utilisant le système; using System.Collections.Generic;

/ * Une approche O (n) existe en utilisant une table de recherche. L'approche consiste à stocker la valeur dans un "bac" qui peut être facilement recherché (par exemple, O (1)) s'il s'agit d'un candidat pour une somme appropriée.

par exemple,

pour chaque a [k] du tableau, nous plaçons simplement le it dans un autre tableau à l'emplacement x - a [k].

Supposons que nous ayons [0, 1, 5, 3, 6, 9, 8, 7] et x = 9

Nous créons un nouveau tableau,

index valeur

9 - 0 = 9     0
9 - 1 = 8     1
9 - 5 = 4     5
9 - 3 = 6     3
9 - 6 = 3     6
9 - 9 = 0     9
9 - 8 = 1     8
9 - 7 = 2     7

ALORS, les seules valeurs qui comptent sont celles qui ont un index dans la nouvelle table.

Donc, disons que lorsque nous atteignons 9 ou égal, nous voyons si notre nouveau tableau a l'indice 9 - 9 = 0. Puisqu'il sait que toutes les valeurs qu'il contient s'ajouteront à 9. (notez dans cette cause il est évident qu'il n'y a que 1 possible mais il peut contenir plusieurs valeurs d'index que nous devons stocker).

Donc, ce que nous finissons par faire, c'est de n'avoir à parcourir le tableau qu'une seule fois. Parce que l'addition est commutative, nous obtiendrons tous les résultats possibles.

Par exemple, lorsque nous arrivons à 6, nous obtenons l'index dans notre nouvelle table sous la forme 9 - 6 = 3. Puisque la table contient cette valeur d'index, nous connaissons les valeurs.

Il s'agit essentiellement de troquer la vitesse contre la mémoire. * /

namespace sum
{
    class Program
    {
        static void Main(string[] args)
        {
            int num = 25;
            int X = 10;
            var arr = new List<int>();
            for(int i = 0; i <= num; i++) arr.Add((new Random((int)(DateTime.Now.Ticks + i*num))).Next(0, num*2));
            Console.Write("["); for (int i = 0; i < num - 1; i++) Console.Write(arr[i] + ", "); Console.WriteLine(arr[arr.Count-1] + "] - " + X);
            var arrbrute = new List<Tuple<int,int>>();
            var arrfast = new List<Tuple<int,int>>();

            for(int i = 0; i < num; i++)
            for(int j = i+1; j < num; j++)
                if (arr[i] + arr[j] == X) 
                    arrbrute.Add(new Tuple<int, int>(arr[i], arr[j]));




            int M = 500;
            var lookup = new List<List<int>>();
            for(int i = 0; i < 1000; i++) lookup.Add(new List<int>());
            for(int i = 0; i < num; i++)        
            {
                // Check and see if we have any "matches"
                if (lookup[M + X - arr[i]].Count != 0)
                {
                    foreach(var j in lookup[M + X - arr[i]])
                    arrfast.Add(new Tuple<int, int>(arr[i], arr[j])); 
                }

                lookup[M + arr[i]].Add(i);

            }

            for(int i = 0; i < arrbrute.Count; i++)
                Console.WriteLine(arrbrute[i].Item1 + " + " + arrbrute[i].Item2 + " = " + X);
            Console.WriteLine("---------");
            for(int i = 0; i < arrfast.Count; i++)
                Console.WriteLine(arrfast[i].Item1 + " + " + arrfast[i].Item2 + " = " + X);

            Console.ReadKey();
        }
    }
}

Fondamentalement, pour éviter les hachages, nous devons créer une table qui peut accepter des insertions aléatoires à des indices quelque peu arbitraires. Par conséquent, j'utilise M pour m'assurer qu'il y a suffisamment d'éléments et pré-allouer un ensemble contigu même si la plupart ne seront pas utilisés. Un ensemble de hachage s'occuperait de cela directement.
AbstractDissonance

Donc, vous utilisez un ensemble de hachage avec une fonction de hachage simple et une taille supérieure à la valeur maximale de votre fonction de hachage?
Chris Hopman

Vous pouvez également utiliser la fonction d'identité pour votre fonction de hachage à ce stade. Autrement dit, mettez un [k] au a [k] -th "bin".
Chris Hopman

Parce que a [k] et X - a [k] sont utilisés comme indices et que j'utilise un tableau, cela signifie que l'indice minimum ne peut pas être 0. Par conséquent, j'ajoute simplement un très grand nombre pour les déplacer vers le haut. Si l'on pouvait créer une fonction de hachage qui fonctionnait pour des valeurs arbitraires, alors ils pourraient utiliser une simple liste sans avoir à faire ce décalage. Le décalage + préallocation permet d'éviter d'avoir à créer un hachage (ou cela pourrait être considéré comme un hachage très simple (et rapide)).
AbstractDissonance

-1

Solution Javascript:

var sample_input = [0, 1, 100, 99, 0, 10, 90, 30, 55, 33, 55, 75, 50, 51, 49, 50, 51, 49, 51];
var result = getNumbersOf(100, sample_input, true, []);

function getNumbersOf(targetNum, numbers, unique, res) {
    var number = numbers.shift();

    if (!numbers.length) {
        return res;
    }

    for (var i = 0; i < numbers.length; i++) {
        if ((number + numbers[i]) === targetNum) {
            var result = [number, numbers[i]];
            if (unique) {
              if (JSON.stringify(res).indexOf(JSON.stringify(result)) < 0) {
                res.push(result);                
              }
            } else {
              res.push(result);
            }
            numbers.splice(numbers.indexOf(numbers[i]), 1);
            break;
        }
    }
    return getNumbersOf(targetNum, numbers, unique, res);
}

Très énifficient .... vous utilisez Stringify (O (n) time and space) à chaque itération ..
Aviad


-4

int [] arr = {1,2,3,4,5,6,7,8,9,0};

var z = (de a dans arr de b dans arr où 10 - a == b sélectionner nouveau {a, b}). ToList;

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.