합이 주어진 숫자와 같은 배열에서 한 쌍의 요소 찾기


122

n 개의 정수 배열과 숫자 X가 주어지면 합이 X와 같은 모든 고유 한 요소 쌍 (a, b)을 찾습니다.

다음은 내 솔루션이며 O (nLog (n) + n)이지만 최적인지 여부는 확실하지 않습니다.

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
배열을 정렬하는 대신 O (1) 집합에 모든 것을 넣는 경우 O (n) 솔루션이 가능합니다.
아논.

1
@Anon U는 그러한 세트를 만드는 방법에 대해 더 자세히 말할 수 있습니까?
Gin

3
해시를 사용하십시오. 대부분의 언어는 표준 라이브러리 어딘가에 상각 된 O (1) HashSet을 갖습니다.
아논.

15
마이너 니트-O (nLog (n) + n)은 O (nLog (n))입니다. Big O 표기법은 지배적 인 항만 유지하고 모든 하위 항을 삭제합니다.
pjs

2
단락 평가 및 개별 주소 지정에 while((arr[i] + arr[j]) <= sum && i < j)유의하십시오 while( i < J && arr[i] + arr[j] <= sum ). (두 번째 서브 루프와 유사)
wildplasser 2013-08-10

답변:


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
첫 번째 루프의 해시 할당 바로 뒤에 두 번째 루프에서 if 문을 넣어 배열을 통해 한 번의 반복으로 수행 할 수도 있습니다.
Alexander Kondratskiy

4
사소한 참고 : 이것은 (알렉산더의 제안과 함께) 쌍의 고유성이 인덱스 (이 답변에서 암시 될 수 있음) 또는 값 (OP에서 보이는 것처럼)에 의해 결정되는지 여부에 관계없이 일부 쌍을 이중 인쇄합니다. 인덱스별로 (O (n ^ 2)) 개의 고유 쌍이있을 수 있습니다 (예 : arr=[1,2,1,2,1,2,1,...]. 값에 의한 고유성을 위해 값 쌍으로 키가 지정된 다른 해시 테이블이 트릭을 수행하는 것처럼 보입니다. 여전히 멋지고 간결하며 우아한 대답입니다. +1
William

2
@codaddict하지만 배열이 매우 크다면 어떨까요? 값의 범위가 매우 큽니까? 따라서 해시 솔루션은 실용성이 떨어집니다. 동일한 대체 및 최적 방법?
Prashant Singh

15
중복이 있으면 어떻게합니까?
zad

2
hash(K - arr[i]) != i어떻게 든 일치의 존재와 부족을 모두 확인 합니까 ? 존재 여부에 대한 별도의 확인이있을 것으로 예상합니다.
Joseph Garvin

185

이 솔루션에는 3 가지 접근 방식이 있습니다.

합계를 T로, n을 배열의 크기로 설정합니다.

접근 방식 1 :
이를 수행하는 순진한 방법은 모든 조합을 확인하는 것입니다 (n 선택 2). 이 철저한 검색은 O (n 2 )입니다.

접근 방식 2 : 
 더 나은 방법은 배열을 정렬하는 것입니다. 이것은 O (n log n)를 취합니다.
그런 다음 배열 A의 각 x에 대해 이진 검색을 사용하여 Tx를 찾습니다. O (nlogn)이 필요합니다.
따라서 전체 검색은 O (n log n)입니다.

접근법 3 :
가장 좋은 방법은 모든 요소를 ​​정렬없이 해시 테이블에 삽입하는 것입니다. 이것은 O (n)을 상수 시간 삽입으로 사용합니다.
그런 다음 모든 x에 대해 그 보수 Tx, 즉 O (1)을 찾을 수 있습니다.
이 접근 방식의 전체 실행 시간은 O (n)입니다.


여기에서 자세한 내용을 참조 할 수 있습니다 . 감사합니다.



배열 요소에 대한 해시 테이블을 어떻게 생성합니까?
Satish Patel

내가 공유 한 링크를 참조하십시오. 요소를 인덱스로 저장하는 병렬 배열을 갖거나 해시 테이블에 요소를 추가하고 여기에 포함을 사용할 수 있습니다. 답장이 늦어서 죄송합니다.
kinshuk4

11
목표 합계의 정확히 절반 인 요소가있는 경우 거짓 양성을 얻을 수 있습니다.
Florian F

2
@Florian_F 정확히 절반 인 요소가있는 특별한 경우는 안 되나요?
Joseph Garvin

1
@jazzz 여기 HashMap을 의미하지만 HashSet도 마찬가지입니다. 다음은 구현입니다 -github.com/kinshuk4/AlgorithmUtil/blob/master/src/com/vaani/… . 도움이 되었기를 바랍니다.
kinshuk4

64

Java로 구현 : codaddict의 알고리즘 사용 (약간 다를 수 있음)

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

}
}

입력 = {2,45,7,3,5,1,8,9}및 합계가10

출력 쌍 :

3,7 
8,2
9,1

솔루션에 대한 몇 가지 참고 사항 :

  • 배열-> O (n) 시간을 한 번만 반복합니다.
  • Hash의 삽입 및 조회 시간은 O (1)입니다.
  • 전체 시간은 O (n)이지만 해시 측면에서 추가 공간을 사용합니다.

1
이것은 입력 배열에 중복이없는 경우에만 좋습니다.
Naren 2015 년

2
@Naren : 주어진 배열에 중복이 있어도 차이가 없습니다
abhishek08aug

1
그것은 대구 중독자가 쓴 것을 구현하지 않으며, 작동하지만 당신이 한 일은 불필요하게 복잡합니다. 그것은에 의미가 put(k-input[i], input[i])당신이 단순화 될 수있다 쓴 (. codaddicts 둔다 유용 값으로 인덱스)for (i:input){ if (intSet.contains(sum-i) { print(i + "," + (sum-i) ); } else {intSet.add(i)}
아드리안 셤

1
괜찮 감사. 다른 사람들의 참조 목적을 위해 방금이 솔루션의 작동 방식을 분석하는 데 어려움이있는 사람들이 제대로 이해할 수 있도록 다른 스레드를 만들었습니다. 여기에 링크가 있습니다. stackoverflow.com/questions/33274952/…
John

2
@ abhishek08aug {1, 1, 1}이하지 않습니다 일
jbakirov

8

자바의 솔루션. 문자열의 ArrayList에 모든 String 요소를 추가하고 목록을 반환 할 수 있습니다. 여기서 나는 그것을 인쇄하고 있습니다.

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 구현 :

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

산출:

1 + 4
2 + 3

2
에 ...보기는 검색 요소에 대한 오버 헤드가 될 것입니다
Nikhil Rupanawar

4

C ++ 11, 런타임 복잡성 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

여기에 솔루션 마녀가 중복 항목을 고려합니다. 자바 스크립트로 작성되었으며 배열이 정렬되었다고 가정합니다. 이 솔루션은 O (n) 시간에 실행되며 변수 외에 추가 메모리를 사용하지 않습니다.

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

대기업 인터뷰에서이 문제를 해결했습니다. 그들은 그것을 가져 갔지만 나는 아닙니다. 그래서 여기 모두를위한 것입니다.

어레이의 양쪽에서 시작하여 천천히 안쪽으로 작업하여 중복 항목이있는 경우 개수를 확인합니다.

쌍만 계산하지만 다시 작업 할 수 있습니다.

  • 쌍을 찾아
  • 쌍 찾기 <x
  • 쌍 찾기> x

즐겨!


이 라인은 무엇을합니까? : if(distI > distK) while(_arr[++i]==curI); else while(_arr[--k]==curK);
Yuriy Chernyshov

그들이 = N 쌍의 합계의 일부인 경우이 라인은 쌍으로 중복 양쪽의 값과 계산을 통해 건너
드론 뇌

3

의 위에)

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)

방법론 : a + b = c, 따라서 (a, b)를 찾는 대신 a = c-b를 찾습니다.


다음과 같이 입력에 중복이있는 경우 작동하지 않습니다. [3, 4, 3, 2, 5] 및 sum = 6
Anton Danilchenko

모든 엣지 케이스 수정, 지금 시도
garg10may

2

Java에서 구현 : 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]);
        }
    }      

}

}

산출:

81, 79
79, 81

중복 쌍 (예 : 80,80) 을 원한다면 if 조건에서 && (Integer) mapping.get (ka [i])! = i를 제거하면됩니다.


C #의 경우 이것은 작동 할 수 있습니다-int k = 16; 정수 개수 = 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 (count);
MukulSharma

2

HackerRank에 대한이 질문에 방금 참석했으며 여기에 내 'Objective 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);
}

누군가에게 도움이되기를 바랍니다.


코드 구문은 알고리즘 자체보다 이해하기 어렵습니다! :)
Rajendra Uppal

1

이것은 루프 내에서 이진 검색 구현을 사용하는 O (n * lg n)의 구현입니다.

#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

파이썬에서

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의 멋진 솔루션입니다. 나는 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

중복 쌍 (1,5), (5,1)을 허용하려면 && !result[sum-l]명령 을 제거하면됩니다.


1

다음은 세 가지 접근 방식에 대한 Java 코드입니다.
1. Map O (n)을 사용하여 HashSet도 여기에서 사용할 수 있습니다.
2. 배열을 정렬 한 다음 BinarySearch를 사용하여 보완 O (nLog (n))를 찾습니다.
3. 기존 BruteForce 두 루프 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

고유 한 요소를 가진 배열을위한 Java의 간단한 프로그램 :

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

아래 쌍을 인쇄하기위한 간단한 Java 코드 스 니펫 :

    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의 또 다른 해결책 : 아이디어는 (sum-currentValue) 값을 저장하는 해시를 생성하고이를 루프의 현재 값과 비교하는 것입니다. 복잡성은 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

내 솔루션-Java-중복 없음

    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

이것은 쌍을 인쇄하고 비트 조작을 사용하여 중복을 방지합니다.

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

비트 조작을 우회하고 인덱스 값을 비교했습니다. 이것은 루프 반복 값 (이 경우 i)보다 작습니다. 이것은 중복 쌍과 중복 배열 요소도 인쇄하지 않습니다.

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 #에서 :

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

이 답변은 솔루션의 성장 순서를 설명하는 경우 더 유용 할 것입니다.
Thomas

0

하나의 솔루션은 이것이 될 수 있지만 최적은 아닙니다 (이 코드의 복잡성은 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

0의 쌍 합계를 찾고 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

함수의 런타임 복잡도는 O (n) 및 공간 : 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

o (n)보다 작은 솔루션은 =>

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

특정 입력에 대해 실패합니다. 게다가 당신은 합계하지 파리 반환해야했다
Aviad

0

목록 이해력을 사용하는 Python의 솔루션

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

O (N 2 )

또한 (a, b) 및 (b, a) 두 개의 순서 쌍을 제공합니다.


언어, (a, b) 및 (b, a) 쌍이 고유한지 여부 및이 질문에 대한 답변 (질문에 명시적인 질문이 포함되지 않음- I am not sure … Thanks for comments)을 언급 할 수 있습니다 . O (n²)에 가까운 복잡도에서 찌르기를 표시 할 수 있습니다.
greybeard

0

O (n)에서 할 수 있습니다. 답을 원하면 알려주세요. 정렬하지 않고 배열을 한 번만 순회하는 것을 포함합니다. 추가의 교환 성을 이용하고 해시를 사용하지 않지만 메모리를 낭비한다는 점도 언급해야합니다.


시스템 사용; System.Collections.Generic 사용;

/ * 조회 테이블을 사용하는 O (n) 접근 방식이 있습니다. 접근 방식은 값이 적절한 합계의 후보 인 경우 쉽게 조회 할 수있는 "bin"(예 : O (1))에 값을 저장하는 것입니다.

예 :

배열의 각 a [k]에 대해 x-a [k] 위치에있는 다른 배열에 넣습니다.

[0, 1, 5, 3, 6, 9, 8, 7]이고 x = 9라고 가정합니다.

새 배열을 만들고

인덱스 값

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

그런 다음 중요한 값은 새 테이블에 대한 인덱스가있는 값입니다.

따라서 우리가 9 이상에 도달하면 새 배열의 인덱스가 9-9 = 0인지 확인합니다. 포함 된 모든 값이 9에 추가된다는 것을 알고 있기 때문에 (이 원인에서는 하나는 가능하지만 저장해야하는 여러 인덱스 값이있을 수 있습니다.)

따라서 효과적으로 우리가하는 일은 어레이를 한 번만 이동하면됩니다. 덧셈은 교환 적이기 때문에 가능한 모든 결과를 얻을 수 있습니다.

예를 들어, 6에 도달하면 새 테이블에 9-6 = 3으로 인덱스를 가져옵니다. 테이블에 해당 인덱스 값이 포함되어 있으므로 값을 알고 있습니다.

이것은 본질적으로 메모리와 속도를 교환하는 것입니다. * /

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

기본적으로 해시를 피하기 위해 임의의 인덱스에서 임의 삽입을 허용 할 수있는 테이블을 만들어야합니다. 따라서 나는 M을 사용하여 충분한 요소가 있는지 확인하고 대부분이 사용되지 않더라도 연속 세트를 미리 할당합니다. 해시 세트는 이것을 직접 처리합니다.
AbstractDissonance

그렇다면 간단한 해시 함수와 해시 함수의 최대 값보다 큰 크기로 해시 세트를 사용하고 있습니까?
Chris Hopman 2011 년

또한이 시점에서 해시 함수에 ID 함수를 사용할 수도 있습니다. 즉, a [k] 번째 "bin"에 a [k]를 넣습니다.
Chris Hopman 2011 년

a [k]와 X-a [k]는 인덱스로 사용되고 저는 배열을 사용하고 있기 때문에 최소 인덱스는 0이 될 수 없다는 것을 의미합니다. 따라서 단순히 아주 큰 숫자를 추가하여 위로 이동합니다. 임의의 값에 대해 작동하는 해시 함수를 만들 수 있다면 이러한 이동을 수행하지 않고도 간단한 목록을 사용할 수 있습니다. shifting + preallocation은 해시를 만들지 않아도됩니다 (또는 매우 간단하고 빠른 해시로 생각할 수 있음).
AbstractDissonance

-1

자바 스크립트 솔루션 :

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

아주 enifficient .... 당신은 캐릭터 라인 화 (O (n)의 시간과 공간) 각각의 반복을 사용하고 ..
Aviad


-4

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

var z = (a in arr에서 b in arr 여기서 10-a == b select new {a, b}). ToList;

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.