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

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



답변

# 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


답변

이 솔루션에는 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)입니다.

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


답변

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)이지만 해시 측면에서 추가 공간을 사용합니다.

답변

자바의 솔루션. 문자열의 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);
    }
}


답변

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


답변

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


답변

여기에 솔루션 마녀가 중복 항목을 고려합니다. 자바 스크립트로 작성되었으며 배열이 정렬되었다고 가정합니다. 이 솔루션은 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

즐겨!