Reputation: 2746
I am trying to implement binary search in Swift 4. The code seems to work, except that the code is falling through to the last return statement. I tried putting it in an else
clause but get a compiler warning saying that control reaches end of non-void. I want it so if the conditions are met, that the code will return early and not exit with the -1 value of the last return statement.
let numbersArray:[Int] = [1, 2, 3, 4, 6, 6, 6, 7, 7, 8, 9, 11, 13, 15, 17, 19, 20]
var first: Int = 0
var last: Int = numbersArray.count - 1
func binarySearch(array: [Int], number: Int) -> Int{
if array.count == 0 {return -1}
else if array.count == 1{
if array[0] == number {return array[0]}
else {return -1}
}
let arrayMiddle: Int = array.count / 2
if number == array[arrayMiddle] {return array[arrayMiddle]}
else if number > array[arrayMiddle]{
first = arrayMiddle + 1
print("first in number > middle \(first)")
last = array.count - 1
print("last in number > middle \(last)")
let slice: [Int] = Array(array[first...last])
binarySearch(array: slice, number: number)
}
else if number < array[arrayMiddle]{
last = arrayMiddle - 1
print("last in number < middle \(last)")
first = 0
print("first in number < middle \(first)")
let slice: [Int] = Array(array[first...last])
binarySearch(array: slice, number: number)
}
print("got to last case")
return -1
}
Upvotes: 2
Views: 390
Reputation:
You should use a switch
and test against your 3 cases:
Also, I would make this generic and an extension on RandomAccessCollection
. That way you don't need to turn each ArraySlice
into an Array
when you call the recursion. The other advantage is that ArraySlice
maintains the indices of the original collection so you won’t need to maintain them yourself. By creating new Array
instances you’re throwing that away.
Lastly, instead of returning a -1 you might want to use an Optional
and return nil
to indicate that the value is not in the collection. That's a fairly standard way to handle it.
My implementation:
extension RandomAccessCollection {
func binarySearch<T>(value: T) -> Self.Index? where
T: Comparable, Self.Element == T {
guard !self.isEmpty else { return nil }
let middle = self.index(self.startIndex, offsetBy: self.count / 2)
switch self[middle] {
case ..<value:
let next = self.index(after: middle)
return self[next...].binarySearch(value: value)
case value:
return middle
default:
return self[..<middle].binarySearch(value: value)
}
}
}
Upvotes: 1
Reputation: 12562
You're recursively calling binarySearch
without returning the result, twice.
Upvotes: 1