Beginner Swift 3: How to find pairs in array that add up to given number

前端 未结 4 1805
深忆病人
深忆病人 2021-01-22 05:40

Need to loop through an array and say whether there are any pairs of numbers that sum to 8

e.g. [1,2,4,4] = yes

Can get it working with lots of nested if stateme

相关标签:
4条回答
  • 2021-01-22 06:20

    Please try the below code. It will give you all the unique pairs whose sum will be equal to the targetSum. It performs the binary search so will be better in performance. The time complexity of this solution is O(NLogN)

    ((arr,targetSum) => {
    if ((arr && arr.length === 0) || targetSum === undefined) {
        return false;
    } else {
        for (let x = 0; x <=arr.length -1; x++) {
            let partnerInPair = targetSum - arr[x];
            let start = x+1;
            let end = (arr.length) - 2;
    
             while(start <= end) {
                let mid = parseInt(((start + end)/2));
                if (arr[mid] === partnerInPair) {
                    console.log(`Pairs are ${arr[x]} and ${arr[mid]} `);
                    break;
                } else if(partnerInPair < arr[mid]) {
                    end = mid - 1;
                } else if(partnerInPair > arr[mid]) {
                    start = mid + 1;
                }
             }
        };
    
    };
    

    })([0,1,2,3,4,5,6,7,8,9], 10)

    0 讨论(0)
  • 2021-01-22 06:21

    You want to check all sums numbers[i] + numbers[j] where i < j, and the easiest way to do so is a nested loop like this:

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        for i in 0..<numbers.count {
            for j in i+1..<numbers.count {
                if numbers[i] + numbers[j] == target {
                    return true
                }
            }
        }
        return false
    }
    

    The array lookups can be avoided by using the enumerated() method and array slices:

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        for (i, x) in numbers.enumerated() {
            for y in numbers[i+1 ..< numbers.count] {
                if x + y == target {
                    return true
                }
            }
        }
        return false
    }
    

    Here x is the current element of the outer loop and i its index. y is the current element of the inner loop which starts enumerating at i + 1.

    Example:

    print(checkPairs(in: [1, 2, 4, 4], forSum: 8))
    print(checkPairs(in: [1, 2, 4, 4], forSum: 7))
    

    The above function could be written more compactly as

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        return numbers.enumerated().contains(where: { (i, x) -> Bool in
            numbers[i+1 ..< numbers.count].contains(target - x)
        })
    }
    

    If the given numbers are in non-decreasing order then you can improve the performance by terminating the inner loop if the target sum cannot be reached:

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        for (i, x) in numbers.enumerated() {
            for y in numbers[i+1 ..< numbers.count] {
                if x + y == target {
                    return true
                }
                if x + y > target {
                    break
                }
            }
        }
        return false
    }
    

    For an array of non-decreasing numbers an even more efficient solution would be to do a binary search for target - x for each array element x. Here is a possible binary search implementation (a variant of https://stackoverflow.com/a/40226976/1187415):

    extension Collection where Iterator.Element: Comparable {
    
        func binarySearch(element: Iterator.Element) -> Bool {
            var low = startIndex
            var high = endIndex
            while low != high {
                let mid = index(low, offsetBy: distance(from: low, to: high)/2)
                if self[mid] < element {
                    low = index(after: mid)
                } else if element < self[mid] {
                    high = mid
                } else {
                    return true
                }
            }
            return false
        }
    }
    

    which can then be used as

    func checkPairs(in numbers: [Int], forSum target: Int) -> Bool {
    
        return numbers.enumerated().contains(where: { (i, x) -> Bool in
            numbers[i+1 ..< numbers.count].binarySearch(element: target - x)
        })
    }
    
    0 讨论(0)
  • 2021-01-22 06:32

    Using two pointer technique.

    Time Complexity: O(n)

    Other solutions mentioned here have Time Complexity: O(n2)

    func isPairSum()-> Bool{
    
    let array = [3, 5, 9, 2, 8, 10, 11]
    let sum = 22
    
    
    var i = 0
    var j = array.count - 1
    
    while i<j {
        
        let valueSum = array[i] + array[j]
        if valueSum == sum {
            return true
        }
        
        else if valueSum > sum {
            j -= 1
        }
        
        else if valueSum < sum {
            i += 1
        }
        
    }
    return false
    

    }

    And If you want the values of the pair, instead of returning Bool, you can return Tuple of type Int.

    0 讨论(0)
  • 2021-01-22 06:36

    You can use nested for loops with indexes:

    for (firstIndex, firstElement) in numbersSet.enumerated() {
        for (secondIndex, secondElement) in numbersSet.enumerated() {
            if firstIndex != secondIndex && firstElement + secondElement == 8 {
                return true
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题