Toplamı belirli bir sayıya eşit olan bir diziden bir çift öğe bulun


122

N tamsayı dizisi verildiğinde ve bir X sayısı verildiğinde, toplamları X'e eşit olan tüm benzersiz öğe çiftlerini (a, b) bulun.

Aşağıdaki benim çözümüm, O (nLog (n) + n), ancak optimal olup olmadığından emin değilim.

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
Diziyi sıralamak yerine her şeyi bir tür O (1) kümesine ayırırsanız bir O (n) çözümü mümkündür.
Anon.

1
@Anon Daha fazla ayrıntı anlatabilir misiniz, böyle bir set nasıl yapılır?
Gin

3
Karmalar kullanın. Çoğu dil, standart kitaplıklarında bir yerde amortize edilmiş O (1) HashSet'e sahip olacaktır.
Anon.

15
Küçük bir nit - O (nLog (n) + n), O (nLog (n)). Büyük O gösterimi yalnızca baskın terimi korur ve tüm düşük dereceli terimleri düşürür.
pjs

2
Kısa devre değerlendirmesine ve tek tek adreslemeye dikkat edin: while((arr[i] + arr[j]) <= sum && i < j)olmalıdır while( i < J && arr[i] + arr[j] <= sum ). (ikinci alt döngü için benzer)
wildplasser

Yanıtlar:


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
Hatta, ikinci döngüden if ifadenizi, birinci döngüdeki hash atamasından hemen sonra koyarak, dizi boyunca tek bir yinelemede bile yapabilirsiniz.
Alexander Kondratskiy

4
Küçük not: Bu (İskender'in önerisinin yanı sıra), bir çiftin benzersizliği indeksle (bu cevaptan anlaşılabileceği gibi) veya değerle (OP'de göründüğü gibi) belirleniyor olsun, bazı çiftleri çift basacaktır. Dizine göre epeyce (O (n ^ 2)) benzersiz çift olabilir, ör arr=[1,2,1,2,1,2,1,...]. Değere göre benzersizlik için, bir değer çiftiyle anahtarlanmış başka bir karma tablo hile yapacak gibi görünüyor. Yine de güzel, kısa ve zarif bir cevap. +1
William

2
@codaddict Ama ya dizi çok büyükse? Demek istediğim, içindeki değerler aralığı çok büyük? Dolayısıyla, hash çözümü o zaman daha az pratik olacaktır. Aynı için alternatif ve en uygun yöntem var mı?
Prashant Singh

15
Ya çiftler varsa?
zad

2
hash(K - arr[i]) != iBir şekilde hem varlığını hem de eşleşmenin olmadığını kontrol ediyor mu ? Ayrı bir mevcudiyet kontrolü olmasını beklerdim.
Joseph Garvin

184

Bu çözüme yönelik 3 yaklaşım vardır:

Toplam T olsun ve n dizinin boyutu olsun.

Yaklaşım 1:
Bunu yapmanın saf yolu, tüm kombinasyonları kontrol etmek olacaktır (n, 2'yi seçin). Bu kapsamlı arama O (n 2 ).

Yaklaşım 2: 
 Diziyi sıralamak daha iyi bir yol olabilir. Bu, O (n log n) alır.
Sonra, A dizisindeki her x için, Tx'i aramak için ikili aramayı kullanın. Bu O (nlogn) alacak.
Dolayısıyla, genel arama O (n log n)

Yaklaşım 3:
En iyi yol, her öğeyi bir karma tabloya (sıralama olmadan) eklemek olacaktır. Bu, sabit zamanlı ekleme olarak O (n) alır.
O zaman her x için, O (1) olan tamamlayıcısı Tx'e bakabiliriz.
Genel olarak bu yaklaşımın çalışma süresi O (n) 'dir.


Buradan daha fazlasını inceleyebilirsiniz .



Dizinin elemanları için nasıl hash tablosu yaratırsınız?
Satish Patel

Paylaştığım bağlantıya bakın. Elementi indeks olarak depolamak için paralel bir dizimiz olabilir veya öğeleri hashtable'a ekleyebilir ve onlarda içerir kullanabilirsiniz. Böyle geç cevap verdiğim için özür dilerim.
kinshuk4

11
Hedef toplamın tam olarak yarısı olan bir öğe varsa, yanlış bir pozitif alabilirsiniz.
Florian F

2
@Florian_F Tam olarak yarısı olan bir öğeye sahip olduğunuz özel bir durum olamaz mı?
Joseph Garvin

1
@jazzz Burada HashMap'i kastediyorum, HashSet de yapacak. İşte uygulama - github.com/kinshuk4/AlgorithmUtil/blob/master/src/com/vaani/… . Umarım yardımcı olur.
kinshuk4

64

Java'da Uygulama: codaddict algoritmasını kullanma (Belki biraz farklı)

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

}
}

İnput = için {2,45,7,3,5,1,8,9}ve Sum ise10

Çıkış çiftleri:

3,7 
8,2
9,1

Çözümle ilgili bazı notlar:

  • Dizi boyunca yalnızca bir kez yineliyoruz -> O (n) zamanı
  • Hash'te ekleme ve arama süresi O (1).
  • Genel zaman O (n) 'dir, ancak hash cinsinden fazladan boşluk kullanır.

1
Bu, YALNIZCA giriş dizisi yinelenmemişse iyidir.
Naren

2
@Naren: Verilen dizide kopya olsa bile fark etmez
abhishek08aug

1
codaddicts'in yazdıklarını uygulamıyor ve yaptığınız şey işe yarasa da, gereksiz karmaşıktır. Anlamsızdır put(k-input[i], input[i])(codaddicts, indeksi yararlı olan değer olarak koyar.) Yazdıklarınız basitleştirilebilirfor (i:input){ if (intSet.contains(sum-i) { print(i + "," + (sum-i) ); } else {intSet.add(i)}
Adrian Shum

1
Tamam teşekkürler. Diğer insanların referans amacıyla, bu çözümün nasıl çalıştığını analiz etmekte zorluk çekenlerin onu doğru bir şekilde anlayabilmesi için başka bir konu oluşturdum. İşte bağlantı: stackoverflow.com/questions/33274952/…
John

2
@ abhishek08aug bu {1, 1, 1} için çalışmayacak
jbakirov

8

Java'da çözüm. Tüm String öğelerini bir dizelerin ArrayList'ine ekleyebilir ve listeyi döndürebilirsiniz. Burada sadece yazdırıyorum.

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 Uygulaması:

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

Çıktı:

1 + 4
2 + 3

2
bak ... öğe aramak için ek yük olacak
Nikhil Rupanawar

4

C ++ 11, çalışma zamanı karmaşıklığı 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

İşte bir çözüm cadısı yinelenen girişleri hesaba katıyor. JavaScript ile yazılmıştır ve dizinin sıralandığını varsayar. Çözüm O (n) zamanında çalışır ve değişken dışında herhangi bir ekstra bellek kullanmaz.

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

Bunu büyük bir şirket için yaptığım bir röportaj sırasında çözdüm. Onu aldılar ama ben değil. İşte burada herkes için.

Dizinin her iki tarafından başlayın ve varsa kopyaları saydığınızdan emin olarak yavaşça içeri doğru ilerleyin.

Yalnızca çiftleri sayar, ancak yeniden çalışılabilir

  • çiftleri bul
  • çiftleri bul <x
  • çiftleri bul> x

Zevk almak!


Bu satırlar ne işe if(distI > distK) while(_arr[++i]==curI); else while(_arr[--k]==curK);
yarar ?

Bu çizgiler, her iki taraftan da yinelenen değerleri atlar ve bir çift toplamın parçasıysa, bunları çiftler olarak sayar = N
Drone Brain

3

O (n)

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)

Metodoloji: a + b = c, yani (a, b) yerine a = c - b arıyoruz


Girişte aşağıdaki gibi kopyalar varsa
uyanmaz

Tüm uç durumlar düzeltildi, şimdi deneyin
garg10may

2

Java'da Uygulama: codaddict algoritmasının kullanılması:

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

}

}

Çıktı:

81, 79
79, 81

Yinelenen çiftler istiyorsanız (örneğin: 80,80) o zaman sadece && (Tamsayı) mapping.get (ka [i])! = İ'yi if koşulundan kaldırın ve gitmeniz iyi olur.


C # için bu iş olabilir - int k = 16; int count = 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]) { ++ saymak; }}} Console.WriteLine (sayım);
MukulSharma

2

HackerRank'teki bu soruya az önce katıldım ve işte benim 'Objective C' Çözümüm :

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

Umarım birine yardımcı olur.


kod sözdizimini anlamak, algoritmanın kendisinden daha zordur! :)
Rajendra Uppal

1

bu, bir döngü içinde ikili arama uygulamasını kullanan O (n * lg n) uygulamasıdır.

#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

Python'da

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

Codeaddict'ten güzel çözüm. Ruby'de bunun bir sürümünü uygulama özgürlüğünü aldım:

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

Yinelenen çiftlere (1,5), (5,1) izin vermek için && !result[sum-l]talimatı kaldırmamız yeterlidir.


1

İşte üç yaklaşım için Java kodu:
1. Harita O (n) kullanılarak, HashSet burada da kullanılabilir.
2. Diziyi sıralayın ve ardından O (nLog (n)) tamamlayıcısını aramak için BinarySearch kullanın
3. Geleneksel BruteForce iki döngü 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

Benzersiz öğelere sahip diziler için java'da basit bir program:

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

Aşağıdaki çiftleri yazdırmak için basit bir Java kod parçası:

    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

Swift'deki başka bir çözüm: fikir, (sum - currentValue) değerlerini depolayan ve bunu döngünün mevcut değeriyle karşılaştıran bir karma oluşturmaktır. Karmaşıklık 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

Çözümüm - Java - Yinelemeler olmadan

    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

Bu, çiftleri yazdırır ve bitsel manipülasyon kullanarak kopyaları önler.

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

Bit manüplasyonunu atladım ve indeks değerlerini karşılaştırdım. Bu, döngü yineleme değerinden daha düşüktür (bu durumda i). Bu, yinelenen çiftleri ve yinelenen dizi öğelerini de yazdırmaz.

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

C # dilinde:

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

Çözümünüzün büyüme sırasını tanımlarsanız bu cevap daha yararlı olacaktır
Thomas

0

Bir Çözüm bu olabilir, ancak optimal değildir (Bu kodun karmaşıklığı O (n ^ 2) şeklindedir):

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

Sıfırın çift toplamını bulan ve k'yi bulmak için değiştirilebilen kodun basit bir python sürümü:

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

İşlevin çalışma zamanı karmaşıklığı da O (n) ve Uzay: O (n) şeklindedir.


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

o (n) 'den küçük çözüm =>

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

Belirli girdiler için başarısız olur. Ayrıca paris dışında bir meblağ iade etmeniz gerekiyordu
Aviad

0

Liste anlama kullanarak Python'da çözüm

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

O (N 2 )

ayrıca iki sıralı çift verir - (a, b) ve (b, a)


Bir dilden, (a, b) ve (b, a) çiftlerinin benzersiz olup olmadığından ve bu yanıtın hangi soruyu yanıtladığından (soru açık bir soru içermez - I am not sure … Thanks for comments) söz edebilirsiniz. Karmaşıklıktaki bıçağı O (n²) 'ye yakın gösterebilirsin.
greybeard

0

O (n) ile yapabilirim. Cevabı istediğinde bana haber ver. Unutmayın, diziyi sıralama olmadan bir kez taramayı içerir, vb ... Ayrıca eklemenin değişmeliğinden yararlandığını ve hash kullanmadığını, ancak belleği boşa harcadığını belirtmeliyim.


Sistem kullanarak; System.Collections.Generic kullanarak;

/ * Bir arama tablosu kullanarak bir O (n) yaklaşımı vardır. Yaklaşım, değeri, uygun bir meblağ için aday ise, kolayca aranabilen (örneğin, O (1)) bir "bölmede" saklamaktır.

Örneğin,

Dizideki her bir a [k] için, onu basitçe x - a [k] konumundaki başka bir diziye koyarız.

[0, 1, 5, 3, 6, 9, 8, 7] ve x = 9'a sahip olduğumuzu varsayalım

Yeni bir dizi oluşturuyoruz,

indeks değeri

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

SONRA, önemli olan tek değerler, yeni tabloya bir indeksi olanlardır.

Diyelim ki, 9'a veya eşitliğe ulaştığımızda, yeni dizimizin 9 - 9 = 0 indeksine sahip olup olmadığını görürüz. Çünkü içerdiği tüm değerlerin 9'a ekleneceğini biliyoruz (bu nedenle, sadece 1 olasıdır, ancak içinde saklamamız gereken birden çok dizin değeri olabilir).

Yani etkili bir şekilde sonunda yaptığımız şey, dizide yalnızca bir kez hareket etmek zorunda kalmaktır. Ekleme değişmeli olduğundan, tüm olası sonuçları elde edeceğiz.

Örneğin 6'ya geldiğimizde indeksi yeni tablomuza 9 - 6 = 3 olarak alıyoruz. Tablo bu indeks değerini içerdiğinden değerleri biliyoruz.

Bu, esas olarak bellek için hızın değiş tokuşu. * /

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

Temel olarak, hash'lerden kaçınmak için, rastgele indekslerde rastgele eklemeler kabul edebilen bir tablo oluşturmalıyız. Bu nedenle, yeterli eleman olduğundan emin olmak ve çoğu kullanılmayacak olsa bile bitişik bir kümeyi önceden tahsis etmek için M'yi kullanıyorum. Bir hash seti bununla doğrudan ilgilenir.
AbstractDissonance

Öyleyse, basit bir hash fonksiyonuna ve hash fonksiyonunuzun maksimum değerinden daha büyük boyuta sahip bir hash set mi kullanıyorsunuz?
Chris Hopman

Bu noktada hash fonksiyonunuz için kimlik fonksiyonunu da kullanabilirsiniz. Yani, a [k] -th "bölmesine" bir [k] koyun.
Chris Hopman

A [k] ve X - a [k] bir indis olarak kullanıldığından ve ben bir dizi kullanıyorum, bu minimum indeksin 0 olamayacağı anlamına gelir. Bu nedenle, onları yukarı kaydırmak için çok büyük bir sayı ekliyorum. Eğer biri rastgele değerler için çalışan bir hash işlevi yapabilseydi, bu kaydırmayı yapmak zorunda kalmadan basit bir liste kullanabilirdi. Kaydırma + ön ayırma, bir karma oluşturma zorunluluğundan kaçınmaya yardımcı olur (veya çok basit (ve hızlı) bir karma olarak düşünülebilir).
AbstractDissonance

-1

Javascript çözümü:

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

Çok yeterli .... her yinelemede Stringify (O (n) zaman ve boşluk) kullanıyorsunuz ..
Aviad


-4

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

var z = (a in arr dan b in arr dan 10 - a == b yeni {a, b} seçin) ToList;

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.