您想检查所有总和 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)
})
}