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


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.