How to write an algorithm to check if the sum of any two numbers in an array/list matches a given number?

前端 未结 14 1951
萌比男神i
萌比男神i 2021-01-30 11:29

How can I write an algorithm to check if the sum of any two numbers in an array/list matches a given number with a complexity of nlogn?

相关标签:
14条回答
  • 2021-01-30 12:08

    Here's a try in C. This isn't marked homework.

    // Assumes a sorted integer array with no duplicates
    void printMatching(int array[], int size, int sum)
    {
       int i = 0, k = size - 1;
       int curSum;
       while(i < k)
       {
          curSum = array[i] + array[k];
          if(curSum == sum)
          {
             printf("Found match at indices %d, %d\n", i, k);
             i++;k--;
          }
          else if(curSum < sum)
          {
             i++;
          }
          else
          {
             k--;
          }
       }
    }
    

    Here is some test output using int a[] = { 3, 5, 6, 7, 8, 9, 13, 15, 17 };

    Searching for 12..
    Found match at indices 0, 5
    Found match at indices 1, 3
    Searching for 22...
    Found match at indices 1, 8
    Found match at indices 3, 7
    Found match at indices 5, 6
    Searching for 4..
    Searching for 50..
    

    The search is linear, so O(n). The sort that takes place behind the scenes is going to be O(n*logn) if you use one of the good sorts.

    Because of the math behind Big-O, the smaller term in additive terms will effectively drop out of your calculation, and you end up with O(n logn).

    0 讨论(0)
  • 2021-01-30 12:09

    I'm sure there's a better way, but here's an idea:

    1. Sort array
    2. For every element e in the array, binary search for the complement (sum - e)

    Both these operations are O(n log n).

    0 讨论(0)
  • 2021-01-30 12:12
    def sum_in(numbers, sum_):
        """whether any two numbers from `numbers` form `sum_`."""
        a = set(numbers) # O(n)
        return any((sum_ - n) in a for n in a) # O(n)
    

    Example:

    >>> sum_in([200, -10, -100], 100)
    True
    
    0 讨论(0)
  • 2021-01-30 12:14

    This can be done in O(n) using a hash table. Initialize the table with all numbers in the array, with number as the key, and frequency as the value. Walk through each number in the array, and see if (sum - number) exists in the table. If it does, you have a match. After you've iterated through all numbers in the array, you should have a list of all pairs that sum up to the desired number.

    array = initial array
    table = hash(array)
    S = sum
    
    for each n in array
        if table[S-n] exists
            print "found numbers" n, S-n
    

    The case where n and table[S-n] refer to the same number twice can be dealt with an extra check, but the complexity remains O(n).

    0 讨论(0)
  • 2021-01-30 12:15
    1. Solved the question in Swift 4.0
    2. Solved in 3 different ways (with 2 different type of return -> Boolean and Indexes)

    A) TimeComplexity => 0(n Log n) SpaceComplexity => 0(n).

    B) TimeComplexity => 0(n^2) SpaceComplexity => 0(1).

    C) TimeComplexity => 0(n) SpaceComplexity => 0(n)

    1. Choose Solution A, B or C depending on TradeOff.

      //***********************Solution A*********************//
      //This solution returns TRUE if any such two pairs exist in the array
      func binarySearch(list: [Int], key: Int, start: Int, end: Int) -> Int? { //Helper Function
      
                  if end < start {
                      return -1
                  } else {
                      let midIndex = (start + end) / 2
      
                      if list[midIndex] > key {
                          return binarySearch(list: list, key: key, start: start, end:  midIndex - 1)
                      } else if list[midIndex] < key {
                          return binarySearch(list: list, key: key, start: midIndex + 1, end: end)
                      } else {
                          return midIndex
                      }
                  }
              }
      
              func twoPairSum(sum : Int, inputArray: [Int]) -> Bool {
      
                  //Do this only if array isn't Sorted!
                  let sortedArray = inputArray.sorted()
      
                  for (currentIndex, value)  in sortedArray.enumerated() {
                      if let indexReturned =  binarySearch(list: sortedArray, key: sum - value, start: 0, end: sortedArray.count-1) {
                          if indexReturned != -1 && (indexReturned != currentIndex) {
                              return true
                          }
                      }
                  }
                  return false
              }
      
       //***********************Solution B*********************//
       //This solution returns the indexes of the two pair elements if any such two pairs exists in the array
       func twoPairSum(_ nums: [Int], _ target: Int) -> [Int] {
      
                  for currentIndex in 0..<nums.count {
                      for nextIndex in currentIndex+1..<nums.count {
                          if calculateSum(firstElement: nums[currentIndex], secondElement: nums[nextIndex], target: target) {
                              return [currentIndex, nextIndex]
                          }
                      }
                  }
      
                  return []
              }
      
              func calculateSum (firstElement: Int, secondElement: Int, target: Int) -> Bool {//Helper Function
                  return (firstElement + secondElement) == target
              }
      
          //*******************Solution C*********************//
         //This solution returns the indexes of the two pair elements if any such two pairs exists in the array
         func twoPairSum(_ nums: [Int], _ target: Int) -> [Int] {
      
                  var dict = [Int: Int]()
      
                  for (index, value) in nums.enumerated() {
                      dict[value] = index
                  }
      
                  for (index, value) in nums.enumerated() {
                      let otherIndex = dict[(target - value)]
                      if otherIndex != nil && otherIndex != index {
                          return [index, otherIndex!]
                      }
                  }
      
                  return []
              }
      
    0 讨论(0)
  • 2021-01-30 12:16

    Here is an algorithm that runs in O(n) if array is already sorted or O(n log n) if it isn't already sorted. Takes cues from lot of other answers here. Code is in Java, but here is a pseudo code as well derived from lot of existing answers, but optimized for duplicates generally

    1. Lucky guess if first and last elements are equal to target
    2. Create a Map with current value and its occurrences
    3. Create a visited Set which contains items we already saw, this optimizes for duplicates such that say with an input of (1,1,1,1,1,1,2) and target 4, we only ever compute for 0 and last element and not all the 1's in the array.
    4. Use these variables to compute existence of target in the array; set the currentValue to array[ith]; set newTarget to target - currentValue; set expectedCount to 2 if currentValue equals newTarget or 1 otherwise

      AND return true only if a. we never saw this integer before AND b. we have some value for the newTarget in the map we created c. and the count for the newTarget is equal or greater than the expectedCount

    OTHERWISE repeat step 4 till we reach end of array and return false OTHERWISE;

    Like I mentioned the best possible use for a visited store is when we have duplicates, it would never help if none of elements are duplicates.

    Java Code at https://gist.github.com/eded5dbcee737390acb4

    0 讨论(0)
提交回复
热议问题