Swift Binary Search失败到最后一个return语句

时间:2018-10-31 02:26:58

标签: swift

我正在尝试在Swift 4中实现二进制搜索。该代码似乎可以正常工作,除了代码陷入最后的return语句之外。我尝试将其放在else子句中,但收到编译器警告,指出控制已到达非void末尾。我想要这样,如果满足条件,则代码将提早返回,并且不会以最后一个return语句的-1值退出。

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
}

2 个答案:

答案 0 :(得分:1)

您要递归地调用binarySearch两次,而不会返回结果。

答案 1 :(得分:1)

您应该使用switch并针对3种情况进行测试:

  1. 该值在中间。在中间部分之后创建一个切片,然后递归调用该切片,并返回该调用的结果。
  2. 该值为中间值,返回中间索引。
  3. 该值在中间值之前。在中间部分之前创建一个切片,然后递归调用该切片,并返回该调用的结果。

此外,我将在RandomAccessCollection上使用通用名称和扩展名。这样,您无需在调用递归时将每个ArraySlice变成一个Array。另一个优点是ArraySlice维护原始集合的索引,因此您无需自己维护它们。通过创建新的Array实例,您可以将其丢弃。

最后,您可能想使用Optional并返回nil来指示该值不在集合中,而不是返回-1。这是一种相当标准的处理方式。

我的实现:

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