给定一个数字列表和一个数字k,返回列表中是否有两个数字加起来等于k

时间:2018-07-12 08:06:09

标签: arrays algorithm time-complexity dynamic-programming subsequence

这个问题是在Google编程采访中提出的。我想到了两种相同的方法:

  1. 查找所有长度的子序列。这样做时,计算两个元素的和,然后检查它是否等于k。如果是,则打印“是”,否则继续搜索。这是蛮力的方法。

  2. 以非降序排列数组。然后从其右端开始遍历数组。假设我们有一个排序后的数组{3,5,7,10},我们希望总和为17。我们将从元素10开始,index = 3,让我们用'j'表示索引。然后包括当前元素并计算required_sum = sum-current_element。之后,我们可以在array [0-(j-1)]中执行二进制或三进制搜索,以查找是否存在一个值等于required_sum的元素。如果找到这样一个元素,我们就会发现长度为2的子序列,其总和就是给定的总和,因此我们可能会中断。如果找不到任何这样的元素,则减小j的索引,并针对长度= length-1的结果子数组重复上述步骤,即在这种情况下通过排除索引3处的元素。

在这里,我们考虑了数组可以同时具有负整数和正整数。

您能提出比这更好的解决方案吗? DP解决方案?可以进一步降低时间复杂度的解决方案。

42 个答案:

答案 0 :(得分:16)

这是Java实现,其时间复杂度与用于对数组进行排序的算法相同。请注意,这比您的第二个想法要快,因为我们不需要在每次检查数字时都在整个数组中搜索匹配的伙伴。

public static boolean containsPairWithSum(int[] a, int x) {
    Arrays.sort(a);
    for (int i = 0, j = a.length - 1; i < j;) {
        int sum = a[i] + a[j];
        if (sum < x)
            i++;
        else if (sum > x)
            j--;
        else
            return true;
    }
    return false;
}

归纳证明: 令a [0,n]是长度为n + 1且p =(p1,p2)的数组,其中p1,p2是整数,并且p1 <= p2(w.l.g.)。假设a [0,n]包含p1和p2。如果不正确,该算法显然是正确的。

基本情况(i = 0,j = n): a [0,-1]不包含p1,a [n,n + 1]不包含p2。

假设: a [0,i-1]不包含a [i],a [j + 1,n]不包含p2。

分步情况(从i到i + 1或从j到j-1):

  1. 假设p1 = a [i]。然后,由于p1 + a [j]
  2. j到j-1类似。

由于在每次迭代中a [0,i-1]和a [j + 1,n]不包含p1和p2,所以a [i,j]确实包含p1和p2。最终a [i] = p1和a [j] = p2,算法返回true。

答案 1 :(得分:16)

借助set的O(N)时间和空间复杂度可以轻松解决此问题。首先将array的所有元素添加到set中,然后遍历array的每个元素并检查K-ar [i]是否为是否存在。

这是Java中具有O(N)复杂度的代码:

boolean flag=false;
HashSet<Long> hashSet = new HashSet<>();
for(int i=0;i<n;i++){
    if(hashSet.contains(k-ar[i]))flag=true;
    hashSet.add(ar[i]);
}
if(flag)out.println("YES PRESENT");
else out.println("NOT PRESENT");

答案 2 :(得分:4)

这是具有O(n)时间复杂度和O(n)空间的Java实现。这个想法是有一个HashMap,它将包含每个带目标的数组元素的补充。如果找到补码,则我们有2个数组元素加和到目标。

 public boolean twoSum(int[] nums, int target) {
    if(nums.length == 0 || nums == null) return false;

    Map<Integer, Integer> complementMap = new HashMap<>();

    for (int i = 0; i < nums.length; i++) {
         int curr = nums[i];
         if(complementMap.containsKey(target - curr)){
           return true;
         }
    complementMap.put(curr, i);
    }
  return false;
}

答案 3 :(得分:4)

如果要查找对数,

pairs = [3,5,7,10]
k = 17
counter = 0

for i in pairs:
    if k - i in pairs:
        counter += 1

print(counter//2)

答案 4 :(得分:2)

def sum_total(list, total):

    dict = {}

    for i in lista:
        if (total - i) in dict:
            return True
        else:
            dict[i] = i

    return False

答案 5 :(得分:2)

Python解决方案:

def FindPairs(arr, k):
    for i in range(0, len(arr)):
        if k - arr[i] in arr:
            return True
    return False        
A = [1, 4, 45, 6, 10, 8]
n = 100
print(FindPairs(A, n))

def findpair(list1, k):
    for i in range(0, len(list1)):
        for j in range(0, len(list1)):
            if k == list1[i] + list1[j]:
                return True    
    return False       
nums = [10, 5, 6, 7, 3]
k = 100
print(findpair(nums, k))

答案 6 :(得分:1)

这是python的实现

arr=[3,5,7,10]
k=17
flag=False
for i in range(0,len(arr)):
    if k-arr[i] in arr:
      flag=True
print( flag )

答案 7 :(得分:1)

JavaScript解决方案:

function hasSumK(arr, k) {
    hashMap = {};
    for (let value of arr) {
        if (hashMap[value]) { return true;} else { hashMap[k - value] = true };
    }
    return false;
}

答案 8 :(得分:1)

我想出了两种C ++解决方案。一种是天真的暴力类型,时间为O(n ^ 2)。

int main() {
int N,K;
vector<int> list;
cin >> N >> K;
clock_t tStart = clock();   
for(int i = 0;i<N;i++) {
    list.push_back(i+1);
}

for(int i = 0;i<N;i++) {
    for(int j = 0;j<N;j++) {
        if(list[i] + list[j] == K) {
            cout << list[i] << " " << list[j] << endl;
            cout << "YES" << endl;
            printf("Time taken: %.2fs\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);
            return 0;
        }
    }
}
cout << "NO" << endl;

printf("Time taken: %f\n", (double)(clock() - tStart)/CLOCKS_PER_SEC);

return 0;}

您想像中的该解决方案在输入值较高时会花费大量时间。

我的第二个解决方案能够在O(N)时间内实现。使用unordered_set,就像上面的解决方案一样。

#include <iostream>
#include <unordered_set>
#include <time.h>

using namespace std;

int main() {
    int N,K;
    int trig = 0;
    int a,b;
    time_t tStart = clock();
    unordered_set<int> u;
    cin >> N >> K;
    for(int i =  1;i<=N;i++) {
        if(u.find(abs(K - i)) != u.end()) {
            trig = 1;
            a = i;
            b = abs(K - i);
        }
        u.insert(i);
    }
    trig ? cout << "YES" : cout << "NO";
    cout << endl;
    cout << a << " " << b << endl;
    printf("Time taken %fs\n",(double) (clock() - tStart)/CLOCKS_PER_SEC);
    return 0;
}

答案 9 :(得分:1)

这里是Python。上)。循环时需要删除当前元素,因为列表可能没有重复的数字。

def if_sum_is_k(list, k):
i = 0
list_temp = list.copy()
match = False
for e in list:
    list_temp.pop(i)
    if k - e in list_temp:
        match = True
    i += 1
    list_temp = list.copy()
return match

答案 10 :(得分:1)

Python

def add(num, k):
for i in range(len(num)):
    for j in range(len(num)):
        if num[i] + num[j] == k:
            return True
return False

答案 11 :(得分:1)

C ++解决方案:

int main(){

    int n;
    cin>>n;
    int arr[n];
    for(int i = 0; i < n; i++)
    {
        cin>>arr[i];
    }
    int k;
    cin>>k;
    int t = false;
    for(int i = 0; i < n-1; i++)
    {
        int s = k-arr[i];
        for(int j = i+1; j < n; j++)
        {
            if(s==arr[j])
            t=true;
        }

    }       
    if (t){
        cout<<"Thank you C++, very cool";
    }
    else{
        cout<<"Damn it!";
    }
        return 0;
}

答案 12 :(得分:1)

使用Scala,一次传递的时间和空间复杂度为O(n)。

import collection.mutable.HashMap

def addUpToK(arr: Array[Int], k: Int): Option[Int] = {

val arrayHelper = new HashMap[Int,Int]()

def addUpToKHelper( i: Int): Option[Int] = {
  if(i < arr.length){
    if(arrayHelper contains k-arr(i) ){
      Some(arr(i))
    }else{
      arrayHelper += (arr(i) -> (k-arr(i)) )
      addUpToKHelper( i+1)
    }

  }else{
   None
  }
}
addUpToKHelper(0)
}

addUpToK(Array(10, 15, 3, 7), 17)

答案 13 :(得分:1)

    function check(arr,k){
    var result = false;
    for (var i=0; i < arr.length; i++){
        for (var j=i+1; j < arr.length; j++){
            result = arr[i] + arr[j] == k;
            console.log(`${arr[i]} + ${arr[j]} = ${arr[i] + arr[j]}`);      
        if (result){
            break;
        }
    }
    return result;
}

JavaScript。

答案 14 :(得分:1)

该解决方案仅需通过数组一次即可找到。初始化哈希集,然后开始迭代数组。如果在集合中找到数组中的当前元素,则返回true,否则将该元素的补码(x-arr [i])添加到集合中。如果数组的迭代结束而没有返回,则意味着不存在总和等于x的对,因此返回false。

  public boolean containsPairWithSum(int[] a, int x) {
    Set<Integer> set = new HashSet<>();
    for (int i = 0; i< a.length; i++) {
        if(set.contains(a[i])) 
            return true;
        set.add(x - a[i]);
    }
    return false;
 }

答案 15 :(得分:1)

这是一个C实现
用于对O(n 2 )的时间和空间复杂度进行排序。
为了解决问题,我们使用 通过递归具有O(n)时空复杂度的单遍。
     / *给定一个数字列表和一个数字k,返回天气列表中的任何两个数字加起来就是k。 例如,给定[10,15,3,7]且k为17,则返回10 + 7为17 奖励:你可以一口气做吗? * /

#include<stdio.h>
int rec(int i , int j ,int k , int n,int array[])
{
  int sum;
  for( i = 0 ; i<j ;)
  {
      sum = array[i] + array[j];
      if( sum > k)
      {
        j--;
      }else if( sum < k)
      {
        i++;
      }else if( sum == k )
      {
        printf("Value equal to sum of array[%d]  = %d and array[%d] = %d",i,array[i],j,array[j]);
        return 1;//True
      }
  }
  return 0;//False
  }
int main()
  {
  int n ;
  printf("Enter The Value of Number of Arrays = ");
  scanf("%d",&n);
  int array[n],i,j,k,x;
  printf("Enter the Number Which you Want to search in addition of Two Number = ");
  scanf("%d",&x);
  printf("Enter The Value of Array \n");
  for( i = 0 ; i <=n-1;i++)
  {
    printf("Array[%d] = ",i);
    scanf("%d",&array[i]);
  }
  //Sorting of Array
  for( i = 0 ; i <=n-1;i++)
  {
     for( j = 0 ; j <=n-i-1;j++)
     {
     if( array[j]>array[j+1])
     {
       //swapping of two using bitwise operator
       array[j] = array[j]^array[j+1];
       array[j+1] = array[j]^array[j+1];
       array[j] = array[j]^array[j+1];
    }
    }
  }
  k = x ;
  j = n-1;
  rec(i,j,k,n,array);
  return 0 ;
}

输出

Enter The Value of Number of Arrays = 4
Enter the Number Which you Want to search in addition of Two Number = 17
Enter The Value of Array
Array[0] = 10
Array[1] = 15
Array[2] = 3
Array[3] = 7
Value equal to sum of array[1]  = 7 and array[2] = 10
Process returned 0 (0x0)   execution time : 54.206 s
Press any key to continue.

答案 16 :(得分:0)

这是Python 3.7中具有O(N)复杂度的代码:

            def findsome(arr,k):
                if  len(arr)<2:
                    return False;
                for e in arr:
                    if k>e and (k-e) in arr:
                        return True
                return False

以及Python 3.7中具有O(N ^ 2)复杂度的最佳案例代码:

            def findsomen2 (arr,k):
                if  len(arr)>1:
                    j=0
                    if arr[j] <k:
                        while j<len(arr):
                            i =0
                            while i < len(arr):
                                if arr[j]+arr[i]==k:
                                    return True
                                i +=1
                            j +=1
                return False

答案 17 :(得分:0)

JavaScript解决方案

function matchSum(arr, k){
  for( var i=0; i < arr.length; i++ ){
    for(var j= i+1; j < arr.length; j++){
       if (arr[i] + arr[j] === k){
        return true;
      }
     }
    }
    return false;
  }

答案 18 :(得分:0)

使用vavr库可以非常简洁地完成此操作:

List<Integer> numbers = List(10, 15, 3, 7);
int k = 17;
boolean twoElementsFromTheListAddUpToK = numbers
                .filter(number -> number < k)
                .crossProduct()
                .map(tuple -> tuple._1 + tuple._2)
                .exists(number -> number == k);

答案 19 :(得分:0)

这是Swift解决方案:

func checkTwoSum(array: [Int], k: Int) -> Bool {
    var foundPair = false
    for n in array {
        if array.contains(k - n) {
            foundPair = true
            break
        } else {
            foundPair = false
        }
    }

    return foundPair
}

答案 20 :(得分:0)

C ++解决方案。

注意:需要C ++ 20(因为使用了“ contains”)

复杂度O(N)(因为在哈希图中插入和搜索的复杂度为O(1))

到Wandbox的有效链接:https://wandbox.org/permlink/KPlzNIlKnTrV5z4X

"documents": [
    {
      "documentId": "1",
      "name": "docusign test document",
      "fileExtension": "pdf",
      "documentBase64": "#base64FileContent#"
    }
  ],

答案 21 :(得分:0)

每日编码问题发布了您所提出问题的一个版本...

  

给出一个数字列表和一个数字k,返回列表中的任何两个数字是否加起来为k。

     

例如,给定[10,15,3,7]且k为17,则由于10 + 7为17,因此返回true。

     

奖金:您可以一次通过吗?

这是基于您的第二个建议的Ruby实现。我不确定是否可以进行优化。

假设:“ 数字列表”实际上是一组数字。

def one_pass_solution
    k = 17
    arr = [10, 15, 3, 7]
    l = 0
    r = arr.length-1
    arr.sort!
    while l < r do
        if arr[l] + arr[r] < k
            l += 1
        elsif arr[l] + arr[r] > k
            r -= 1
        else
            return true
        end
    end
    return false
end

答案 22 :(得分:0)

大多数发布的解决方案并没有将k解释为列表中任何数字的两倍,因此它们的解决方案将生成假阳性。以下代码也说明了这种情况。由于涉及集合的运算为O(1),因此我们的最终解决方案是单遍O(N)解决方案。

from typing import Optional, List


def add_upto_k(k: int, array: Optional[List] = None) -> bool:
    assert array, "Non array input"
    assert len(array) != 0, "Array is empty"

    diff_set = set()

    for iterator in array:
        diff = k - iterator
        if iterator in diff_set:
            return True
        diff_set.add(diff)
    return False


if __name__ == "__main__":
    print(add_upto_k(k=17, array=[10, 15, 3, 7])) # True
    print(add_upto_k(k=15, array=[10, 15, 3, 7])) # False
    print(add_upto_k(k=20, array=[10, 15, 3, 10])) # True
    print(add_upto_k(k=20, array=[10, 15, 3, 7])) # False

答案 23 :(得分:0)

使用快速中的设置将我的答案设为O(n)

func twoNumbersEqualToK(array: [Int], k: Int) -> Bool {
  let objectSet = Set(array)

  for element in objectSet {
    let x = k - element

    if objectSet.contains(x) {
      return true
    }
  }

  return false
}

答案 24 :(得分:0)

复杂度为O(N)

private static boolean check_add_up(int[] numbers, int total) {
        Set<Integer> remainders = new HashSet<>();
        int remainder;
        for (int number : numbers ) {
            if (remainders.contains(number)) {
                return true;
            }

            remainder = total - number;

            if(!remainders.contains(remainder)){
                remainders.add(remainder);
            }
        }

        return false;
    }

答案 25 :(得分:0)

带有O(n)的Javascript答案

function checkPair(arr, n) {
  for (var i in arr) {
    if (arr.includes(n - arr[i])) {
      return true;
    }
  }
  return false;
}

var a = [4,2,8,7,5,77,6,3,22];
var n = 99;
var m = 100;

console.log(checkPair(a, n));
console.log(checkPair(a, m));

答案 26 :(得分:0)

这是一个scala解决方案,它超出了布尔结果,如果存在则返回该对:

def thereIs(list2check: List[Int], k: Int): List[Int] =  list2check match {
    case Nil => Nil
    case x :: tail => tail.flatMap{
        case element if (element+ x)==k =>List(element,x)
        case element if (element+ x)!=k => Nil
    } ++ thereIs(tail,k)
}

答案 27 :(得分:0)

使用Java中的HashSet可以一次性完成,也可以使用O(n)的时间复杂度

import java.util.Arrays;
import java.util.HashSet;

public class One {
    public static void main(String[] args) {
        sumPairsInOne(10, new Integer[]{8, 4, 3, 7});
    }


    public static void sumPairsInOne(int sum, Integer[] nums) {
        HashSet<Integer> set = new HashSet<Integer>(Arrays.asList(nums));

        //adding values to a hash set
        for (Integer num : nums) {
            if (set.contains(sum - num)) {
                System.out.print("Found sum pair => ");
                System.out.println(num + " + " + (sum - num) + " = " + sum);
                return;
            }
        }

        System.out.println("No matching pairs");


    }
}

答案 28 :(得分:0)

选中此项-https://www.geeksforgeeks.org/given-an-array-a-and-a-number-x-check-for-pair-in-a-with-sum-as-x/

在方法2中,它是以O(n)的时间和空间复杂度实现的。

HashSet使用HashTable实现。因此, .contains 方法需要恒定的时间O(1), 使得程序的整体时间复杂度为O(n)。

答案 29 :(得分:0)

我对日常编码问题的回答

# Python 2.7
def pairSumK (arr, goal):
  return any(map(lambda x: (goal - x) in arr, arr))

arr = [10, 15, 3, 7]
print pairSumK(arr, 17)

答案 30 :(得分:0)

JavaScript解决方案

此函数使用2个参数并遍历列表的长度,并且在循环内还有另一个循环,该循环将一个数字与列表中的其他数字相加,并检查那里的和是否等于k。

const list = [10, 15, 3, 7];
const k = 17;

function matchSum(list, k){
 for (var i = 0; i < list.length; i++) {
  list.forEach(num => {
   if (num != list[i]) {
    if (list[i] + num == k) {
     console.log(`${num} + ${list[i]} = ${k} (true)`);
    }
   }
  })
 }
}

matchSum(list, k);

答案 31 :(得分:0)

Python代码:

L = list(map(int,input("Enter List: ").split()))
k = int(input("Enter value: "))

for i in L:
    if (k - i) in L:
        print("True",k-i,i)

答案 32 :(得分:0)

以下是两个非常快速的Python实现(说明了[1,2]2的输入应返回false的情况;换句话说,您不能仅将数字加倍,因为它指定了“任何两个”)。

第一个循环浏览术语列表,并将每个术语添加到所有先前看到的术语中,直到达到期望的总和。

def do_they_add(terms, result):
    first_terms = []
    for second_term in terms:
        for first_term in first_terms:
            if second_term + first_term == result:
                return True
        first_terms.append(second_term)
    return False

此项从结果中减去每个项,直到达到项列表中的差值为止(使用a+b=c -> c-a=b规则)。 enumerate和奇数列表索引的使用是根据该答案的第一句话来排除当前值。

def do_they_add_alt(terms, result):
    for i, term in enumerate(terms):
        diff = result - term
        if diff in [*terms[:i - 1], *terms[i + 1:]]:
            return True
    return False

如果您确实允许自己添加数字,则第二种实现方式可以简化为:

def do_they_add_alt(terms, result):
    for term in terms:
        diff = result - term
        if diff in terms:
            return True
    return False

答案 33 :(得分:0)

我已经在Go Lang中尝试了该解决方案。但是,它消耗O(n ^ 2)的时间。

package main

import "fmt"

func twoNosAddUptoK(arr []int, k int) bool{
    // O(N^2)
    for i:=0; i<len(arr); i++{
        for j:=1; j<len(arr);j++ {
            if arr[i]+arr[j] ==k{
                return true
            }
        }
    }
    return false
}

func main(){
    xs := []int{10, 15, 3, 7}
    fmt.Println(twoNosAddUptoK(xs, 17))
}

答案 34 :(得分:0)

我是用Scala实现的

  def hasSome(xs: List[Int], k: Int): Boolean = {
    def check(xs: List[Int], k: Int, expectedSet: Set[Int]): Boolean = {
      xs match {
        case List() => false
        case head :: _ if expectedSet contains head => true
        case head :: tail => check(tail, k, expectedSet + (k - head))
      } 
    }
    check(xs, k, Set())
  }

答案 35 :(得分:0)

这是一个javascript解决方案:

function ProblemOne_Solve()
{
    const k = 17;
    const values = [10, 15, 3, 8, 2];
    for (i=0; i<values.length; i++) {
        if (values.find((sum) => { return k-values[i] === sum} )) return true;
    }
    return false;
}

答案 36 :(得分:0)

JavaScript

const findPair = (array, k) => {
  array.sort((a, b) => a - b);
  let left = 0;
  let right = array.length - 1;

  while (left < right) {
    const sum = array[left] + array[right];
    if (sum === k) {
      return true;
    } else if (sum < k) {
      left += 1;
    } else {
      right -= 1;
    }
  }

  return false;
}

答案 37 :(得分:0)

Python实现: 使用字典将以O(n)复杂度执行代码。我们将(desired_output-current_input)作为键存储在字典中。然后,我们将检查字典中是否存在该数字。在字典中进行搜索的平均复杂度为O(1)。

def PairToSumK(numList,requiredSum):
    dictionary={}
    for num in numList:
        if requiredSum-num not in dictionary:
            dictionary[requiredSum-num]=0
        if num in dictionary:
            print(num,requiredSum-num)
            return True
    return False

arr=[10, 5, 3, 7, 3]
print(PairToSumK(arr,6))

答案 38 :(得分:0)

我的C#实现:

 bool  isPairPresent(int[] numbers,int value)
 {
        for (int i = 0; i < numbers.Length; i++)
        {
            for (int j = 0; j < numbers.Length; j++)
            {
                if (value - numbers[i] == numbers[j])
                    return true;
            }
        }
        return false;
 }

答案 39 :(得分:0)

C#解决方案:

bool flag = false;
            var list = new List<int> { 10, 15, 3, 4 };
            Console.WriteLine("Enter K");
            int k = int.Parse(Console.ReadLine());

            foreach (var item in list)
            {
                flag = list.Contains(k - item);
                if (flag)
                {
                    Console.WriteLine("Result: " + flag);
                    return;
                }
            }
            Console.WriteLine(flag);

答案 40 :(得分:-1)

Python:

l1 = [10、15、3、7]

k = 18

[如果l1中的(k-i)等于l1中的i]

答案 41 :(得分:-2)

Python解决方案:

def TwoNumsAddToK(lis, k):
    dict = {}
    for num in lis:
        dict[num] = 0
        if k - num in dict:
            return True
    return False