3 二分查詢變種總結
時間複雜度概念還不清楚的可以先看****這個文章:
由於二分查詢每次查詢都是從陣列中間切開查詢,所以每次查詢,剩餘的查詢數為上一次的一半,從下表可以清晰的看出查詢次數與剩餘元素數量對應關係
肯定是大於等於1,也就是n(2
k)\frac
(2k)n
>=1,我們計算時間複雜度是按照最壞的情況進行計算,也就是是查到剩餘最後乙個數才查到我們想要的資料,也就是
n (2
k)\frac
(2k)n
>=1
=>n=2
kn=2^k
n=2k
=>k=l
og2n
k=log_2^n
k=log2
n所以二分查詢的時間複雜度為o(l
og2n
)o(log_2^n)
o(log2
n).
二分查詢是乙個基礎的演算法,也是面試中常考的乙個知識點。二分查詢就是將查詢的鍵和子陣列的中間鍵作比較,如果被查詢的鍵小於中間鍵,就在左子陣列繼續查詢;如果大於中間鍵,就在右子陣列中查詢,否則中間鍵就是要找的元素。
* 二分查詢,找到該值在陣列中的下標,否則為-1
*/static
intbinaryserach
(int
array,
int key)
else
if(array[mid]
< key)
else
}return-1
;}每次移動left和right指標的時候,需要在mid的基礎上+1或者-1, 防止出現死迴圈, 程式也就能夠正確的執行。
注意:**中的判斷條件必須是while (left <= right),否則的話判斷條件不完整,比如:array[3] = ;待查詢的鍵為5,此時在(low < high)條件下就會找不到,因為low和high相等時,指向元素5,但是此時條件不成立,沒有進入while()中。
關於二分查詢,如果條件稍微變換一下,比如:陣列之中的資料可能可以重複,要求返回匹配的資料的最小(或最大)的下標;更近一步, 需要找出陣列中第乙個大於key的元素(也就是最小的大於key的元素的)下標,等等。 這些,雖然只有一點點的變化,實現的時候確實要更加的細心。
二分查詢的變種和二分查詢原理一樣,主要就是變換判斷條件(也就是邊界條件),如果想直接看如何記憶這些變種的竅門,請直接翻到本文最後。下面來看幾種二分查詢變種的**:
查詢第乙個相等的元素,也就是說等於查詢key值的元素有好多個,返回這些元素最左邊的元素下標。
// 查詢第乙個相等的元素
static
intfindfirstequal
(int
array,
int key)
else}if
(left < array.length && array[left]
== key)
return-1
;}
查詢最後乙個相等的元素,也就是說等於查詢key值的元素有好多個,返回這些元素最右邊的元素下標。
// 查詢最後乙個相等的元素
static
intfindlastequal
(int
array,
int key)
else}if
(right >=
0&& array[right]
== key)
return-1
;}
查詢最後乙個等於或者小於key的元素,也就是說等於查詢key值的元素有好多個,返回這些元素最右邊的元素下標;如果沒有等於key值的元素,則返回小於key的最右邊元素下標。
// 查詢最後乙個等於或者小於key的元素
static
intfindlastequalsmaller
(int
array,
int key)
else
}return right;
}
查詢最後乙個小於key的元素,也就是說返回小於key的最右邊元素下標。
// 查詢最後乙個小於key的元素
static
intfindlastsmaller
(int
array,
int key)
else
}return right;
}
查詢第乙個等於或者大於key的元素,也就是說等於查詢key值的元素有好多個,返回這些元素最左邊的元素下標;如果沒有等於key值的元素,則返回大於key的最左邊元素下標。
// 查詢第乙個等於或者大於key的元素
static
intfindfirstequallarger
(int
array,
int key)
else
}return left;
}
查詢第乙個等於key的元素,也就是說返回大於key的最左邊元素下標。
// 查詢第乙個大於key的元素
static
intfindfirstlarger
(int
array,
int key)
else
}return left;
}
// 這裡必須是 <=
while
(left <= right)
else
}return ***;
二分查詢變種較多,不過它們的「套路」是一樣的,以上**就是其套路,如何快速寫出二分查詢的**,只需按照以下步驟即可:
首先判斷出是返回left,還是返回right
因為我們知道最後跳出while (left <= right)迴圈條件是right < left,且right = left - 1。最後right和left一定是卡在"邊界值"的左右兩邊,如果是比較值為key,查詢小於等於(或者是小於)key的元素,則邊界值就是等於key的所有元素的最左邊那個,其實應該返回left。
以陣列為例,如果需要查詢第乙個等於或者小於3的元素下標,我們比較的key值是3,則最後left和right需要滿足以下條件:
我們比較的key值是3,所以此時我們需要返回left。
判斷出比較符號
int mid =
(left + right)/2
;if(array[mid]
? key)
else
也就是這裡的 if (array[mid] ? key) 中的判斷符號,結合步驟1和給出的條件,如果是查詢小於等於key的元素,則知道應該使用判斷符號》=,因為是要返回left,所以如果array[mid]等於或者大於key,就應該使用》=,以下是完整**.
// 查詢小於等於key的元素
int mid =
(left + right)/2
;if(array[mid]
>= key)
else
二分查詢及其變種
返回帶查詢元素key的下標。若沒有key元素,則返回 1。注意 1 while迴圈的條件是low high 2 每次迭代hi mid 1 或lo mid 1 二分查詢,找到該值在陣列中的下標,否則為 1 static int binaryserach int array,int key else i...
二分查詢及其變種
首先說下普通二分查詢的思路 普通二分查詢是在乙個沒有重複的排序陣列中,找到目標值 思路就是先從中間找,如果中間值大於目標值,說明目標值在左半區 如果中間值小於目標值,說明目標值在右邊,當中間值等於目標值,返回他的下標,這裡的陣列預設都不為空 給定乙個有序陣列和乙個關鍵字,找到該值在陣列中的下標,否則...
二分查詢演算法及其變種
前言 二分查詢演算法也稱為折半查詢演算法,是一種在查詢演算法中普遍使用的演算法。其演算法的基本思想是 在有序表中,取中間的記錄作為比較關鍵字,若給定值與中間記錄的關鍵字相等,則查詢成功 若給定的值小於中間記錄的關鍵字,則在中間記錄的左半區間繼續查詢 若給定值大於中間記錄的關鍵字,則在中間記錄的右半區...