初学者Swift 3:如何在数组中找到加起来给定数字的对

时间:2017-05-02 08:39:05

标签: arrays swift sequence

需要遍历数组并说明是否有任何数字对总和为8

e.g。 [1,2,4,4] =是

可以使用大量嵌套的if语句,但如果数组发生变化,这将是不切实际的。

我理想的做法就是为我说i if i +(i.indexPosition +1 {我旁边的数字}))== 8然后打印true,如果不是false,则转到下一个数字集的迭代

想知道是否有人知道可以在这里使用的更好的逻辑?非常感谢!!

E.g。

var numbersSet = [1, 2, 4, 4]

for i in numbersSet2 {

    var targetSum = 8

    if i + numbersSet2[1] == targetSum {

        print("True")
    } else { // Nested if statements here

        print("False")
    }
}

5 个答案:

答案 0 :(得分:2)

您想检查所有金额numbers[i] + numbers[j]在哪里 i < j,最简单的方法是这样的嵌套循环:

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
}

使用enumerated()方法可以避免数组查找 和数组切片:

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
}

这里x是外循环的当前元素,i是它 指数。 y是内循环的当前元素,它开始 枚举i + 1

示例:

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

上述函数可以更紧凑地编写

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

如果给定的数字是非递减顺序,那么你可以 通过终止内循环来提高性能 如果无法达到目标金额:

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
}

对于非递减数字的数组,效率更高 解决方案是为target - x执行二进制搜索 对于每个数组元素x。这是一个可能的二进制搜索 实现(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
    }
}

然后可以用作

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

答案 1 :(得分:1)

您可以使用带索引的嵌套for循环:

for (firstIndex, firstElement) in numbersSet.enumerated() {
    for (secondIndex, secondElement) in numbersSet.enumerated() {
        if firstIndex != secondIndex && firstElement + secondElement == 8 {
            return true
        }
    }
}

答案 2 :(得分:1)

以上所有答案都很好,但都返回 Bool 值,因此我正在编写解决方案以将所有可能的对存储在字典中并打印它们。

以下解决方案将避免重复,从而将复杂性降至最低。

var numbers = [13,2,4,5,6,3,7,90,11,10,12,1,8,9]
var dictionary1 : [Int : Int] = [:]
var j = 0
func findPair(numbers : [ Int ] , number : Int) -> [Int : Int] {
    
    for (i , _) in numbers.enumerated() {
        
        j = i
        while j < numbers.count {
            
            if i != j {
                let addition = numbers[i] + numbers[j]
                if addition == number {
                    dictionary1[numbers[i]] = numbers[j]
                }
            }
            j += 1
        }
    }
    return dictionary1
}

let result = findPair(numbers: numbers, number: 11)
print(dictionary1)

输出 - [10: 1, 4: 7, 5: 6, 3: 8, 2: 9]

这些都是给定数字的对。即 11

答案 3 :(得分:0)

使用两个指针技术。

时间复杂度:O(n)

此处提到的其他解决方案具有时间复杂度: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

}

如果想要该对的值,则可以返回Int类型的Tuple,而不是返回Bool。

答案 4 :(得分:-1)

请尝试以下代码。它将为您提供所有唯一对,其总和将等于targetSum。它执行二进制搜索,因此性能会更好。该解决方案的时间复杂度为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)