二分查詢錯誤事例分析

2021-06-01 04:45:35 字數 1912 閱讀 3629

#include int search(int array, int n, int v)

else if (array[middle] < v)

else

}return -1;

}

在這裡,迴圈的開始處,把迴圈遍歷的序列區間是這樣的:

left =0, right = n;

while (left < right)

//  迴圈體

也就是說,這是乙個左閉右開的區間:[0, n).

但是,在迴圈內部, 卻不是這樣操作的:

middle = (left + right) / 2;

if (array[middle] > v)

right = middle - 1;

else if (array[middle] < v)

left = middle + 1;

else

return middle;

當array[middle] > v條件滿足時, 此時v如果存在的話必然在左閉右開區間[left, middle)中, 因此,當這個條件滿足時, right應該為middle, 而在這裡, right賦值為middle - 1了, 那麼, 就有可能遺漏array[middle - 1] = v的情況.

這是一種典型的二分查詢演算法寫錯的情況

,迴圈體是左閉右開區間

,而迴圈體內部卻是採用左閉右閉區間的演算法進行操作.

下面給出的兩種正確的演算法,演算法search是左閉右閉區間演算法,而演算法search2是左閉右開區間演算法,可以對比一下差異.

int search(int array, int n, int v)

else if (array[middle] < v)

else

}return -1;

}

int search2(int array, int n, int v)

else if (array[middle] < v)

else

}return -1;

}

下面再給出另一種典型的錯誤的二分查詢演算法,當查詢的元素不在序列內時,它可能造成程式的死迴圈.

int search(int array, int n, int v)

else if (array[middle] < v)

else

}return -1;

}

從迴圈條件來看

,這個演算法的操作區間是左閉右閉區間的

,因此當

array[middle] > v時,v

如果存在的話應該在

[left, middle- 1]中,

因此此時

right

應該是middle - 1,

而不是middle;

類似的,

當array[middle] < v時,

下一次操作的區間應該是

[middle + 1, right]中.

而當元素不存在這個序列中時

,演算法在乙個錯誤的區間中迴圈

,但是又不能終止迴圈

,於是就造成了死迴圈.

總結:

1、錯誤一:可能存在漏取值  (從迴圈體開始 與 迴圈體內的區間來判斷)

2、錯誤二:誤入死迴圈           (找乙個不在序列內的元素做測試用例)

演算法所操作的區間

,是左閉右開區間

,還是左閉右閉區間

,這個區間

,需要在迴圈初始化

,迴圈體是否終止的判斷中

,以及每次修改

left,right

區間值這三個地方保持一致

,否則就可能出錯

.

二分查詢深度分析

總結一句話就是 思路很簡單,細節是魔鬼,hhhh。本部落格 幾個最常用的二分查詢場景 尋找乙個數 尋找左側邊界 尋找右側邊界。public int binarysearch int nums,int target return 1 答 舉個例子推一下即可得知。因為當left 4,right 6時,此...

leetcode 二分查詢錯誤版本

你是產品經理,目前正在帶領乙個團隊開發新的產品。不幸的是,你的產品的最新版本沒有通過質量檢測。由於每個版本都是基於之前的版本開發的,所以錯誤的版本之後的所有版本都是錯的。假設你有 n 個版本 1,2,n 你想找出導致之後所有版本出錯的第乙個錯誤的版本。你可以通過呼叫 bool isbadversio...

迭代二分查詢二分查詢

在寫這篇文章之前,已經寫過了幾篇關於改迭代二分查詢主題的文章,想要了解的朋友可以去翻一下之前的文章 bentley在他的著作 writing correct programs 中寫道,90 的計算機專家不能在2小時內寫出完整確正的二分搜尋演算法。難怪有人說,二分查詢道理單簡,甚至小學生都能明確。不過...