(3)iOS程序猿算法學習——二分查找「Binary Search」

寫二分的時候最糾結的就是循環條件,而且特別容易出現死循環。
來看一個最經典的二分:給你一個數組,再給你個 target,找到 target 在數組中的位置,找不到就返回 - 1。有些題目是讓你找第一個出現的位置,也有讓你找到最后出現的位置。

1.時間復雜度:

每次能去掉一半即 logn

2.實現方式:

while循環遞歸
我更推薦 while 循環,因為遞歸有個潛在的問題就是 stack over flow(堆棧溢出),而且在實際工程中是盡量避免遞歸的。雖然遞歸寫起來方便,也不容易出錯。

3.實現關鍵點

我總結了下,一共有以下四點
start + 1 < end

這個是 while 循環條件,即退出循環的條件是 start +1 >= end,首先來看 start + 1 == end 這個時候,start 和 end 是相鄰的關系。start > end 兩者相交了。而且這樣的寫法不可能出現死循環,比如下面這種寫法很容易就出現了死循環。

while (start < end) {// 1,2
  mid = ...; //1
  if (...) {
    start = mid; 
 } else {
     end = mid;
 }
}

  • ** mid = start + (end - start)/2**

這個寫法看起來很妖艷兒,有點裝逼,實際上能還是很有用的。因為傳統的寫法 (start + end) / 2 ,這樣有個潛在的問題,就是如果 start ,end 足夠大的話就會出現溢出的問題。這個點可以看出工程師還是很細心的。

  • ** source[mid] ==, <, > **

循環開始,根據mid和target的關系,看看怎么移動 end、start 指針,根據具體題目移動。一般來說等于 mid 就可以了

  • ** source[start] source[end] ? target**

退出循環后,判斷 start 、 end 和 target 的關系。

下面直接上代碼了,這樣寫的好處是只用處理最后兩個數的邏輯,很容易擴展。類似于遞歸到最底層只處理1個或者的關系。

+ (NSInteger)binarySearch:(NSArray *)source target:(NSInteger)target {
    if (source.count == 0) {
        return -1;
    }
    NSInteger start = 0;
    NSInteger end = source.count - 1;
    NSInteger mid = 0;
    while (start + 1 < end) {
        mid = start + (end - start) / 2;
        if ([source[mid] integerValue] == target) { // 相鄰就退出
            return mid;
        } else if ([source[mid] integerValue] < target) { 
            start = mid;
        } else {
             end = mid;
        }
    }
    if ([source[start] integerValue] == target) {
        return start;
    }
    if ([source[end] integerValue] == target) {
        return end;
    }
    
    return -1;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容