Suchen Sie ein Elementpaar aus einem Array, dessen Summe einer bestimmten Zahl entspricht


122

Finden Sie bei einem gegebenen Array von n ganzen Zahlen und einer gegebenen Zahl X alle eindeutigen Paare von Elementen (a, b), deren Summation gleich X ist.

Das Folgende ist meine Lösung, es ist O (nLog (n) + n), aber ich bin nicht sicher, ob es optimal ist oder nicht.

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
Eine O (n) -Lösung ist möglich, wenn Sie alles in eine Art O (1) -Satz einfügen, anstatt das Array zu sortieren.
Anon.

1
@Anon Kannst du mehr Details darüber erzählen, wie man ein solches Set baut?
Gin

3
Verwenden Sie Hashes. Die meisten Sprachen haben irgendwo in ihren Standardbibliotheken ein amortisiertes O (1) HashSet.
Anon.

15
Ein kleines nit - O (nLog (n) + n) ist O (nLog (n)). Die Big O-Notation behält nur den dominanten Term bei und löscht alle Terme niedrigerer Ordnung.
pjs

2
Beachten Sie die Kurzschlussauswertung und die Off-by-One-Adressierung: while((arr[i] + arr[j]) <= sum && i < j)sollte sein while( i < J && arr[i] + arr[j] <= sum ). (ähnlich für die zweite Subloop)
Wildplasser

Antworten:


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
Sie können dies sogar in einer Iteration durch das Array tun, indem Sie Ihre if-Anweisung aus der zweiten Schleife direkt nach der Hash-Zuweisung in die erste Schleife einfügen.
Alexander Kondratskiy

4
Kleinere Anmerkung: Dies (sowie Alexanders Vorschlag) wird einige Paare doppelt drucken, unabhängig davon, ob die Eindeutigkeit eines Paares durch den Index (wie aus dieser Antwort hervorgeht) oder durch den Wert (wie es im OP scheint) bestimmt wird. Es könnte einige (O (n ^ 2)) eindeutige Paare nach Index geben, z arr=[1,2,1,2,1,2,1,...]. Für die Eindeutigkeit nach Wert scheint es, als würde eine andere Hash-Tabelle, die von einem Wertepaar verschlüsselt wird, den Trick tun. Immer noch eine schöne, kompakte, elegante Antwort. +1
William

2
@codaddict Aber was ist, wenn das Array sehr groß ist? Ich meine, der Wertebereich darin ist sehr groß? Die Hash-Lösung ist dann weniger praktisch. Gibt es eine alternative und optimale Methode dafür?
Prashant Singh

15
Was ist, wenn es Duplikate gibt?
zad

2
Hat hash(K - arr[i]) != iüberprüfen irgendwie sowohl Vorhandensein und das Fehlen eines Spiels? Ich würde erwarten, dass es eine separate Überprüfung auf Anwesenheit gibt.
Joseph Garvin

185

Es gibt drei Ansätze für diese Lösung:

Die Summe sei T und n sei die Größe des Arrays

Ansatz 1:
Der naive Weg, dies zu tun, wäre, alle Kombinationen zu überprüfen (n wählen Sie 2). Diese erschöpfende Suche ist O (n 2 ).

Ansatz 2: 
 Ein besserer Weg wäre, das Array zu sortieren. Dies dauert O (n log n).
Verwenden Sie dann für jedes x in Array A die binäre Suche, um nach Tx zu suchen. Dies wird O (nlogn) dauern.
Die Gesamtsuche lautet also O (n log n).

Ansatz 3:
Der beste Weg wäre, jedes Element in eine Hash-Tabelle einzufügen (ohne zu sortieren). Dies nimmt O (n) als konstante Zeiteinfügung.
Dann können wir für jedes x einfach sein Komplement Tx nachschlagen, das O (1) ist.
Insgesamt beträgt die Laufzeit dieses Ansatzes O (n).


Sie können hier mehr verweisen. Danke.



Wie würden Sie eine Hash-Tabelle für die Elemente des Arrays erstellen?
Satish Patel

Verweisen Sie auf den Link, den ich geteilt habe. Wir können ein paralleles Array haben, um das Element als Index zu speichern, oder Sie können die Elemente zur Hashtabelle hinzufügen und deren Verwendung enthalten. Entschuldigung für eine so späte Antwort.
Kinshuk4

11
Sie erhalten möglicherweise ein falsches Positiv, wenn es ein Element gibt, das genau die Hälfte der Zielsumme beträgt.
Florian F

2
@Florian_F Kannst du nicht einfach einen Sonderfall haben, in dem du ein Element hast, das genau halb ist?
Joseph Garvin

1
@jazzz Ich meine HashMap hier, obwohl HashSet auch tun wird. Hier ist die Implementierung - github.com/kinshuk4/AlgorithmUtil/blob/master/src/com/vaani/… . Ich hoffe es hilft.
Kinshuk4

64

Implementierung in Java: Verwenden des Codaddict-Algorithmus (möglicherweise etwas anders)

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

}
}

Für Eingabe = {2,45,7,3,5,1,8,9}und wenn Summe ist10

Ausgabepaare:

3,7 
8,2
9,1

Einige Hinweise zur Lösung:

  • Wir durchlaufen das Array nur einmal -> O (n) Zeit
  • Die Einfüge- und Suchzeit in Hash ist O (1).
  • Die Gesamtzeit ist O (n), obwohl sie zusätzlichen Speicherplatz in Bezug auf Hash verwendet.

1
Dies ist NUR dann gut, wenn das Eingabearray keine Duplikate enthält.
Naren

2
@Naren: Es macht keinen Unterschied, auch wenn das angegebene Array Duplikate enthält
abhishek08aug

1
Es implementiert nicht, was Codaddicts geschrieben haben, und was Sie getan haben, obwohl es funktioniert, ist unnötig kompliziert. Es ist bedeutungslos put(k-input[i], input[i])(Codaddicts setzt den Index als nützlichen Wert). Was Sie geschrieben haben, kann vereinfacht werdenfor (i:input){ if (intSet.contains(sum-i) { print(i + "," + (sum-i) ); } else {intSet.add(i)}
Adrian Shum

1
Okay danke. Als Referenzzweck für andere Personen habe ich gerade einen weiteren Thread erstellt, damit diejenigen, die Schwierigkeiten bei der Analyse der Funktionsweise dieser Lösung haben, diese richtig verstehen können. Hier ist der Link: stackoverflow.com/questions/33274952/…
John

2
@ abhishek08aug das wird nicht funktionieren für {1, 1, 1}
jbakirov

8

Lösung in Java. Sie können alle String-Elemente zu einer ArrayList von Strings hinzufügen und die Liste zurückgeben. Hier drucke ich es gerade aus.

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

Python-Implementierung:

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

Ausgabe:

1 + 4
2 + 3

2
schau
rein

4

C ++ 11, Laufzeitkomplexität 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

Hier ist eine Lösung, die doppelte Einträge berücksichtigt. Es ist in Javascript geschrieben und setzt voraus, dass das Array sortiert ist. Die Lösung wird in O (n) -Zeit ausgeführt und verwendet außer Variablen keinen zusätzlichen Speicher.

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;
}

Ich habe dies während eines Interviews für ein großes Unternehmen gelöst. Sie haben es genommen, aber nicht ich. Also hier ist es für alle.

Beginnen Sie auf beiden Seiten des Arrays und arbeiten Sie sich langsam nach innen, um sicherzustellen, dass Duplikate gezählt werden, falls vorhanden.

Es zählt nur Paare, kann aber überarbeitet werden

  • finde die Paare
  • finde Paare <x
  • finde Paare> x

Genießen!


Was machen diese Zeilen?: if(distI > distK) while(_arr[++i]==curI); else while(_arr[--k]==curK);
Yuriy Chernyshov

Diese Zeilen überspringen doppelte Werte von beiden Seiten und zählen sie als Paare, wenn sie Teil einer Paarsumme sind = N
Drone Brain

3

Auf)

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)

Methodik: a + b = c, also suchen wir statt (a, b) nach a = c - b


Wok nicht, wenn Sie Duplikate in der Eingabe haben, wie folgt: [3, 4, 3, 2, 5] und sum = 6
folgt Anton Danilchenko

Alle
Randfälle

2

Implementierung in Java: Verwenden des Codaddict-Algorithmus:

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

}

}

Ausgabe:

81, 79
79, 81

Wenn Sie auch doppelte Paare (z. B. 80,80) möchten, entfernen Sie einfach && (Integer) Mapping.get (ka [i])! = I aus der if-Bedingung und Sie können loslegen.


für C # kann dies Arbeit sein - int k = 16; int count = 0; int [] intArray = {5, 7, 11, 23,8,9,15,1,10,6}; für (int i = 0; i <intArray.Length; i ++) {für (int j = i; j <intArray.Length; j ++) {if ((k - intArray [i]) == intArray [j]) { count ++; }}} Console.WriteLine (Anzahl);
MukulSharma

2

Ich habe gerade diese Frage auf HackerRank besucht und hier ist meine 'Objective C' -Lösung :

-(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);
}

Hoffe es hilft jemandem.


Die Codesyntax ist schwer zu verstehen als der Algorithmus selbst! :)
Rajendra Uppal

1

Dies ist die Implementierung von O (n * lg n) unter Verwendung einer binären Suchimplementierung innerhalb einer Schleife.

#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

In 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

Schöne Lösung von Codeaddict. Ich habe mir erlaubt, eine Version davon in Ruby zu implementieren:

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

Um doppelte Paare (1,5), (5,1) zuzulassen, müssen wir nur die && !result[sum-l]Anweisung entfernen


1

Hier ist Java-Code für drei Ansätze:
1. Mit Map O (n) kann auch HashSet hier verwendet werden.
2. Sortieren Sie das Array und suchen Sie dann mit BinarySearch nach dem Komplement O (nLog (n)).
3. Traditionelle BruteForce-Zwei-Schleifen 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

Ein einfaches Programm in Java für Arrays mit eindeutigen Elementen:

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

Ein einfaches Java-Code-Snippet zum Drucken der folgenden Paare:

    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

Eine andere Lösung in Swift: Die Idee ist, einen Hash zu erstellen, der Werte von (sum - currentValue) speichert und diesen mit dem aktuellen Wert der Schleife vergleicht. Die Komplexität ist 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

Meine Lösung - Java - Ohne Duplikate

    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

Dies druckt die Paare und vermeidet Duplikate durch bitweise Manipulation.

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

Ich habe die Bitmanuplikation umgangen und nur die Indexwerte verglichen. Dies ist weniger als der Schleifeniterationswert (in diesem Fall i). Dadurch werden auch die doppelten Paare und doppelten Array-Elemente nicht gedruckt.

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

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

Diese Antwort wäre nützlicher, wenn Sie die Reihenfolge des Wachstums Ihrer Lösung beschreiben
Thomas

0

Eine Lösung kann dies sein, aber nicht optimal (Die Komplexität dieses Codes ist 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

Eine einfache Python-Version des Codes, die eine Paarsumme von Null findet und geändert werden kann, um k zu finden:

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

Die Laufzeitkomplexität der Funktion ist ebenfalls O (n) und 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

weniger als o (n) Lösung ist =>

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

Schlägt bei bestimmten Eingaben fehl. Außerdem mussten Sie eine Summe nicht in Paris zurückgeben
Aviad

0

Lösung in Python mit Listenverständnis

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

O (N 2 )

gibt auch zwei geordnete Paare an - (a, b) und (b, a)


Sie können eine Sprache erwähnen, ob die Paare (a, b) und (b, a) eindeutig sind und welche Frage diese beantwortet (die Frage enthält keine explizite - I am not sure … Thanks for comments). Sie könnten den Komplexitätsstich näher an O (n²) bezeichnen.
Graubart

0

Ich kann es in O (n) tun. Lassen Sie mich wissen, wann Sie die Antwort wollen. Beachten Sie, dass das Array einfach einmal ohne Sortierung usw. durchlaufen wird. Ich sollte auch erwähnen, dass es die Kommutativität der Addition ausnutzt und keine Hashes verwendet, sondern Speicher verschwendet.


mit System; using System.Collections.Generic;

/ * Ein O (n) -Ansatz existiert unter Verwendung einer Nachschlagetabelle. Der Ansatz besteht darin, den Wert in einem "Behälter" zu speichern, der leicht nachgeschlagen werden kann (z. B. O (1)), wenn es sich um einen Kandidaten für eine geeignete Summe handelt.

z.B,

Für jedes a [k] im Array setzen wir es einfach in ein anderes Array an der Stelle x - a [k].

Angenommen, wir haben [0, 1, 5, 3, 6, 9, 8, 7] und x = 9

Wir erstellen ein neues Array,

indiziert Wert

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

DANN sind nur diejenigen Werte von Bedeutung, die einen Index in der neuen Tabelle haben.

Wenn wir also 9 oder gleich erreichen, sehen wir, ob unser neues Array den Index 9 - 9 = 0 hat. Da wir wissen, dass alle darin enthaltenen Werte zu 9 addiert werden (beachten Sie, dass es in diesem Fall offensichtlich nur einen gibt 1 möglich, aber es kann mehrere Indexwerte enthalten, die wir speichern müssen).

Am Ende müssen wir uns also nur einmal durch das Array bewegen. Da die Addition kommutativ ist, erhalten wir alle möglichen Ergebnisse.

Wenn wir zum Beispiel 6 erreichen, erhalten wir den Index als 9 - 6 = 3 in unsere neue Tabelle. Da die Tabelle diesen Indexwert enthält, kennen wir die Werte.

Dies ist im Wesentlichen ein Kompromiss zwischen Geschwindigkeit und Speicher. * /

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();
        }
    }
}

Um Hashes zu vermeiden, müssen wir grundsätzlich eine Tabelle erstellen, die zufällige Einfügungen an etwas willkürlichen Indizes akzeptieren kann. Daher verwende ich M, um sicherzustellen, dass genügend Elemente vorhanden sind, und ordne eine zusammenhängende Menge vorab zu, obwohl die meisten nicht verwendet werden. Ein Hash-Set würde sich direkt darum kümmern.
AbstractDissonance

Sie verwenden also ein Hash-Set mit einer einfachen Hash-Funktion und einer Größe, die größer ist als der Maximalwert Ihrer Hash-Funktion?
Chris Hopman

Sie können an dieser Stelle auch die Identitätsfunktion für Ihre Hash-Funktion verwenden. Das heißt, setzen Sie ein [k] in den a [k] -ten "Behälter".
Chris Hopman

Da a [k] und X - a [k] als Indizes verwendet werden und ich ein Array verwende, bedeutet dies, dass der Mindestindex nicht 0 sein kann. Daher füge ich einfach eine sehr große Zahl hinzu, um sie nach oben zu verschieben. Wenn man eine Hash-Funktion erstellen könnte, die für beliebige Werte funktioniert, könnte man eine einfache Liste verwenden, ohne diese Verschiebung durchführen zu müssen. Die Verschiebung + Vorbelegung hilft zu vermeiden, dass ein Hash erstellt werden muss (oder man könnte sich einen sehr einfachen (und schnellen) Hash vorstellen).
AbstractDissonance

-1

Javascript-Lösung:

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);
}

Sehr enifficient .... Sie verwenden Stringify (O (n) Zeit und Raum) jede Iteration ..
Aviad


-4

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

var z = (von a in arr von b in arr wobei 10 - a == b neues {a, b} auswählen). ToList;

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.