陣列中的二分查詢

2021-09-24 05:37:16 字數 2999 閱讀 2567

先談談二分查詢,二分查詢是一種非常高效的查詢演算法,例題如下:

給定乙個整形有序陣列,如何找出某一整數是否在這個陣列中,以及返回該整數所對應的下標?

此題最簡單的方法就是遍歷一遍原陣列來判斷是否存在,這也是順序查詢,時間複雜度為o(n)。還可以建立乙個雜湊表,但是這種方法的空間複雜度為o(n)。所以,此時最佳的演算法便是二分查詢,其時間複雜度為o(logn),空間複雜度為o(1)。

下面給出二分查詢演算法遞迴與非遞迴的兩種形式:

private int binarysearch(int nums, int left, int right, int target) 

int mid = left + (right - left) / 2;//防止數值溢位

if (nums[mid] > target) else if (nums[mid] < target)

return mid;

}

private int binarysearch(int nums, int left, int right, int target)  else if (nums[mid] < target)  else 

}return -1;

}

也許,這並不足以證明二分查詢的威力,下面擴充套件一下原題目。

假設按照公升序排序的陣列在預先未知的某個點上進行了旋轉

( 例如,陣列 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。

搜尋乙個給定的目標值,如果陣列中存在這個目標值,則返回它的索引,否則返回 -1 。你可以假設陣列中不存在重複的元素。

這個題我給出兩種解題思路,而這兩種方法都用到了二分查詢。

第一種方法:二分查詢加分治演算法,第一次取得原陣列的中間元素進行比較(中間元素恰好是目標值的情況單獨拿出來即可),不難發現總有一側的元素是有序,另外一側的元素是無序的,有序的一側直接復用二分查詢即可,而無序的一側仿照剛才思路再來一次,就這樣通過二分來實現遞迴分治來判斷目標值是否存在。

具體**如下:

public int search1(int nums, int target) 

private int find(int nums, int left, int right, int target)

//判斷邊界條件

int mid = left + (right - left) / 2;

if (target == nums[left])

if (target == nums[right])

if (target == nums[mid])

if (target > nums[right] && target < nums[left])

//判斷的核心**

if (nums[mid] < nums[right]) else

} else else }}

private int binarysearch(int nums, int left, int right, int target) else if (nums[mid] < target) else

}return -1;

}

第二種方法:二分查詢加二分查詢,先通過整體的二分查詢得到陣列的旋轉點,從而不難得出以旋轉點為中心的左右兩側都是有序陣列,進行再分別對其兩側進行二分查詢來判斷目標值是否存在。

具體**如下:

public int search2(int nums, int target) 

int partition = findpartition(nums);

if (partition != -1) else if (target > nums[nums.length - 1]) else

}return binarysearch(nums, 0, nums.length - 1, target);

}private int findpartition(int nums)

if (mid != left && nums[mid] < nums[mid - 1])

if (nums[mid] < nums[left]) else

}return -1;

}

通過上面的題目就足以見得二分查詢的威力不小。

其實就上面的題目還能進一步拓展,就是把上述陣列中不存在重複的元素的條件去掉。

此時題目難度又增加了一些,因為有重複的元素必然會影響到二分查詢的效能和查詢的正確性,從而乙個很直接的想法就是去重,即在上述**的基礎上加上一段可以去掉陣列重複元素的**即可。

具體**如下:

public boolean search1(int nums, int target) 

private boolean find(int nums, int left, int right, int target)

while (left < right && nums[left] == nums[left + 1])

while (left < right && nums[right] == nums[right - 1])

int mid = left + (right - left) / 2;

if (target == nums[left])

if (target == nums[right])

if (target == nums[mid])

if (target > nums[right] && target < nums[left])

if (nums[mid] < nums[right]) else

} else else }}

private boolean binarysearch(int nums, int left, int right, int target) else if (nums[mid] < target) else

}return false;

}

陣列 二分查詢

package a array.a twopointssearch 二分查詢,增刪。優點 查詢速度比無序陣列快 缺點 刪除慢,因為資料項必須向前移動來填補已刪除資料項的洞 增加慢,需要移動大於增加數所對用索引後面的所有值 author administrator author administrat...

陣列的二分查詢

public class myorderarray public myorderarray int maxsize 新增有序陣列 public void insert long value 比如在2456這個陣列中查入3,那456要整體向後移動,從6後面開始操作 for int j elemnet ...

有序陣列中的二分查詢

最近看一些演算法題發現這些問題到最後落實到實現上都是程式設計基礎的體現,包括對基本的for,if,else,while等語句的理解程度,還有對迴圈遞迴的理解。所以還是得回歸最基本的演算法,現在去學習那些高深複雜的dp,kmp,紅黑樹未免有點好高騖遠。目前應該堅持基礎,打好基礎,畢竟不是cs科班出身。...