从数组中找到一对元素,其总和等于给定的数字

Gin*_*Gin 121 algorithm

给定n个整数的数组并给出数字X,找到所有唯一的元素对(a,b),其总和等于X.

以下是我的解决方案,它是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--;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

kin*_*uk4 179

该解决方案有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).


你可以在这里详细介绍.谢谢.


  • 如果元素恰好是目标总和的一半,则可能会出现误报. (11认同)
  • @Florian_F你不能只是特殊情况,你有一个正好一半的元素? (2认同)

cod*_*ict 132

# 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
Run Code Online (Sandbox Code Playgroud)

  • 您甚至可以通过数组进行一次迭代,在第一个循环中的哈希赋值之后,通过第二个循环放置if语句. (26认同)
  • 如果有重复怎么办? (15认同)
  • 次要注意:这(以及亚历山大的建议)将双打一些对,无论一对的唯一性是由索引(可能从这个答案暗示)还是由值(如OP中所示)确定的.索引可能有很多(O(n ^ 2))个唯一对,例如`arr = [1,2,1,2,1,2,1,...]`.对于值的唯一性,似乎另一个由值对键控的哈希表可以解决问题.仍然是一个不错,紧凑,优雅的答案.+1 (4认同)
  • @codaddict但是如果数组非常大呢?我的意思是它的值范围非常大?因此,哈希解决方案将不那么实用.任何替代和最佳方法? (2认同)
  • `hash(K - arr [i])!= i`以某种方式检查存在和缺少匹配?我希望有一个单独的存在检查. (2认同)

Ram*_*bo7 61

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

}
}
Run Code Online (Sandbox Code Playgroud)

对于input = {2,45,7,3,5,1,8,9},如果Sum为10

输出对:

3,7 
8,2
9,1
Run Code Online (Sandbox Code Playgroud)

关于解决方案的一些说明:

  • 我们只通过数组迭代一次 - > O(n)时间
  • Hash中的插入和查找时间为O(1).
  • 总时间是O(n),尽管它在散列方面使用了额外的空间.

  • @Naren:即使给定数组中有重复项,它也没有区别 (2认同)
  • @ abhishek08aug这不适用于{1,1,1} (2认同)

小智 7

java中的解决方案.您可以将所有String元素添加到字符串的ArrayList并返回列表.我在这里打印出来.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)