本章總結二分查詢、旋轉陣列及擴充套件。二分查詢也稱折半查詢(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.如果待查詢...