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--;
        }
    }
}
Gin
la source
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
codaddict
la source
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.


kinshuk4
la source
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.
Rambo7
la source
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);
    }
}
Vikram Dave
la source
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
CHAUD
la source
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;
}
iamantony
la source
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!

Drone cerveau
la source
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

garg10may
la source
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.

Arpit Agarwal
la source
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.

Saru
la source
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;
}
Lokesh Basu
la source
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
Nikhil Rupanawar
la source
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

obaqueiro
la source
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]+")");
        }
    }
}

}
utilisateur1529412
la source
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]);
       }
    }
}
Pankaj Jaiswal
la source
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);
        }
    }
    }
karthikbv
la source
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)
Duyen-Hoa
la source
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("------------------------------");
}
LiozM
la source
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]));
            }
        }
    }
}
codewarrior
la source
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);
            }
        }
    }
}
Surya
la source
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]);
Chrishan
la source
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;
   }
}
Shridutt Kothari
la source
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).

Billz
la source
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;
}
Bruce Zu
la source
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}
Shishir Arora
la source
É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)

Ashwin Aravind
la source
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();
        }
    }
}
RésuméDissonance
la source
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);
}
gor181
la source
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;

Bhavesh Lad
la source