二分查詢由淺入深

2021-09-18 07:35:37 字數 4011 閱讀 5322

本章總結二分查詢、旋轉陣列及擴充套件。
二分查詢也稱折半查詢(binary search),它是一種效率較高的查詢方法。但是,折半查詢要求:

① 線性表必須採用順序儲存結構;

② 而且表中元素按關鍵字有序排列。   將陣列分為3部分:中值左、中值、中值右。將要查詢的資料跟中值比較,小於中值在左半部分找,等於中值返回,大於中值在右半部分查詢。左右部分查詢過程同理,是乙個遞迴過程。如圖,某陣列中查詢元素6:

* 測試

* @param args

*/public

static

void

main

(string[

] args)

;int k =6;

system.out.

println

("查詢k為:"

+ k +

",位置為:"

+binarysearch

(arr, k,

0, arr.length -1)

);}/**

* 二分查詢

* @param k

* @return k的索引

*/static

intbinarysearch

(int

arr ,

int k,

int left ,

int right)

else

if(k > arr[mid]

)else

}return-1

;}以上為最簡單的二分查詢原理,我相信理解起來應該很容易,下面我們要舉一反三,看一下二分查詢的變種或應用。我相信很多人對這個並不陌生,沒錯,它來自劍指offer,這個考察的是對二分查詢的理解和應用能力。原題為:輸入乙個遞增排序的陣列的乙個旋轉,輸出最小元素。例如,輸入,輸出1。

我們使用效率較高的二分查詢,為什麼使用二分?因為陣列是部分遞增排序,而且前半部分比後半部分值都大。所以,基本符合二分的前提條件。

1. 首先,簡單分析一下二分查詢都幹了些什麼?不就是確定中值,然後進行比較麼。所以我們還是從中值的角度去考慮,那麼此時mid會有兩種情況:

① mid位於左邊公升序部分,② mid位於右邊公升序部分。

2. 旋轉陣列求最小值過程**

特殊情況,mid、right和left值都相等,此時只能進行順序查詢:

3. **示例

package com.cnepay.algorithm;

/** * 旋轉陣列中查詢最小值

* @author wxq

* */

public

class

searchrotatearray

;// int arr = {};

int index =

findminnuminrotatearray

(arr,

0, arr.length-1)

; system.out.

println

(index);if

(index !=-1

)else

}/**

* 查詢旋轉陣列的最小值

* @param array

* @param left

* @param right

* @return

*/static

intfindminnuminrotatearray

(int

array,

int left,

int right)

//特殊情況

if(array[mid]

== array[left]

&& array[left]

== array[right]

)//mid在左邊遞增陣列中,最小值在右邊,移動左指標

if(array[mid]

>= array[left]

)//mid 在右邊遞增陣列中,最小值在左邊,移動右指標

else

if(array[mid]

<= array[right])}

return mid;

}//順序查詢

static

intfindinorder

(int

array,

int left,

int right)

}return minnum;

}}

4.區別於普通二分查詢:

① 查詢k值的方式不同,普通的是直接比較k,而這裡k的確定是根據左右指標相鄰 和 旋轉陣列的特性,比如30 2 ,此時2肯定為最小值;

② 有特殊情況,需要單獨處理。

③ 共同點是:都是通過比較大小,然後移動指標。  這個看上去又複雜一點了,上一小節中查詢最小值,確定的條件就是right - left = 1,即左右指標相鄰,但是這裡的查詢k值情況就多了:判斷mid位置的同時,還要判斷k值的位置。

其實,思路跟旋轉陣列是一致的。只不過增加了k值位置判斷的情況。具體就不畫圖分析了,直接上**吧。**示例如下:

/**

* 旋轉陣列中查詢指定k值

* @author wxq

* */

public

class

searchkrotatearray

;int

arr =

;int k =30;

int index =

findkinrotatearray

(arr,k,

0, arr.length-1)

; system.out.

println

("查詢k為:"

+ k +

",位置為:"

+index );}

/** * 旋轉陣列中查詢k值

* @param arr

* @param k

* @param left

* @param right

* @return

*/static

intfindkinrotatearray

(int

arr,

int k,

int left ,

int right)

//左邊部分是遞增陣列

if(arr[mid]

>= arr[left]

)//右邊部分是遞增陣列

else

}return-1

;}/** * 順序查詢

* @param arr

* @param k

* @return

*/static

intfindinorder

(int

arr,

int k)

return-1;}}

時間複雜度無非就是while迴圈的次數!總共有n個元素,漸漸跟下去就是n,n/2,n/4,…n/2^k(接下來操作元素的剩餘個數),其中k就是迴圈的次數。

由於你n/2^k取整後》=1,即領n/2 ^k =1,可得k=log2n,(是以2為底,n的對數)。所以時間複雜度可以表示o(h)=o(log2n)。(此過程來自百科)     本文講了二分查詢、旋轉陣列查詢最小值和查詢指定k,思路是一致的,只不過相對於二分查詢 ----> 旋轉陣列多了旋轉特性的判斷 ----> 旋轉陣列查詢k又多了k值位置的判斷。

迭代二分查詢二分查詢

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

1128 二分 二分查詢

時間限制 10000ms 單點時限 1000ms 記憶體限制 256mb 描述nettle最近在玩 艦 因此nettle收集了很多很多的船 這裡我們假設nettle氪了很多金,開了無數個船位 去除掉重複的船之後,還剩下n 1 n 1,000,000 種不同的船。每一艘船有乙個稀有值,任意兩艘船的稀有...

二分查詢及變種二分查詢

二分查詢也稱折半查詢 binary search 它的查詢效率很好。二分查詢有乙個要求是必須採用順序儲存結構,而且表種的元素是有序的。只有滿足這個條件我們才能使用二分查詢。查詢條件 查詢區域的左邊界,小於等於查詢區域的右邊界 查詢過程 1.迴圈條件 查詢條件 2.計算序列中間下標位置 3.如果待查詢...