我想在Swift中编写一个很好的Binary Search实现,以下似乎是一种在所有情况下都能克服传递上下限的技巧。
func binarySearch(arr: [Int], target: Int, _ lowerBound: Int? = 0, _ upperBound: Int? = 0) -> Int? {
var ub = upperBound
if (ub == 0 ) { ub = arr.count
}
深入说明:我已经编写了以下形式的一组测试:
XCTAssertEqual(binarySearch(arr: [1,2,3,4], target: 5), nil)
而且我不想在第一个实例中将上下限传递给二进制搜索。
我的函数头看起来像:
func binarySearch(arr: [Int], target: Int, _ lowerBound: Int? = 0, _ upperBound: Int? = 0) -> Int? {
在每次二进制搜索的递归调用中,下界要么为零,要么为传递的参数,这很有意义。但是上限没有。
现在我想写一些类似的
func binarySearch(arr: [Int], target: Int, _ lowerBound: Int? = 0, _ upperBound: arr.count) -> Int? {
但是显然这是不可能的。
我什至想添加以下内容(但显然不能,因为upperBound是一个let常量):
if (upperBound == 0 ) {upperBound = arr.count}
我想使用:
func binarySearch(arr: [Int], target: Int, _ lowerBound: Int? = 0, _ var upperBound: Int? = 0) -> Int? {
但是看起来这不再是迅速的功能。
我离开时不得不按如下方式使用一个额外的变量,因为这太乱了!
func binarySearch(arr: [Int], target: Int, _ lowerBound: Int? = 0, _ upperBound: Int? = 0) -> Int? {
var ub = upperBound
if (ub == 0 ) {ub = arr.count}
答案 0 :(得分:1)
我将使上限参数成为可选参数(如您所愿),但将默认参数设置为nil
。然后,将您的本地ub
值创建为:
let ub = upperbound ?? arr.count
下限应该是非可选的,默认值为0
。
func binarySearch(arr: [Int], target: Int, _ lowerBound: Int = 0, _ upperBound: Int? = nil) -> Int? {
let ub = upperBound ?? arr.count
答案 1 :(得分:1)
这是常见的情况。递归函数的签名可能需要比其入口点更多的参数。解决此问题的最佳方法是使用嵌套函数。
func binarySearch(_ array: [Int], for target: Int) -> Int? {
func binarySearch(_ array: [Int], for: Int, lowerBound: Int, upperBound: Int) -> Int? {
// your implementation here
}
return binarySearch(array, for: target, lowerBound: 0, upperBound: array.count)
}
有关更多Swifty代码,建议您尝试使用以下方法进行转换:
Int
这是一个入门示例:
extension RandomAccessCollection where Self.IndexDistance == Int {
public func binarySearch(for target: Element) -> Int? {
return binarySearch(for: target, inRange: 0 ..< self.count)
}
private func binarySearch(for target: Element, inRange range: CountableRange<Int>) -> Int? {
return nil // Your implementation here
}
}