二分查詢彙總1
阿新 • • 發佈:2021-01-21
技術標籤:LeeCode程式碼演算法二分法資料結構leetcode
二分查詢
二分查詢是常用的查詢演算法之一,凡是看見有關log時間複雜度的要求,都要想到二分查詢,前提是搜尋列表是有序的,才能應用二分查詢。
這裡我記錄一篇寫的比較好的二分查詢的文章,以備後續反覆學習。
二分查詢總結
左開右閉二分查詢
對於尋找左右邊界的二分搜尋,常見的手法是使用左閉右開的「搜尋區間」,在刷力扣的一道題中遇見了採用左開右閉的方式去尋找元素的右分割線的位置,,因此自己簡單做了一點程式碼去實現該想法。
package com.heu.wsq.leetcode;
/**
* @author wsq
* @date 2021/1/20
*/
public class BinarySearch {
public int customSearch(int[] nums, int target){
int n = nums.length;
// 確定搜尋區間
// 注意:這時候只是確定了區間的邊界,但是還沒有確定區間的開閉情況
int left = 0;
int right = n;
// while中取等號,可以實現雙閉
while (left < right) {
// 求中間值,採用left + (right - left) / 2的方式可以防止溢位
// 由於java中的向下取整同時暗示著,取下限,而不取上限,確定區間 是左閉右開的[left, right)
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
// 找到目標值,直接返回
return mid;
}else if (nums[mid] < target){
// 中間值小於目標值,證明目標值可能在右邊
// 由於是左閉右開的,因此下一步的搜尋區間應該是[mid + 1, right)
left = mid + 1;
}else if (nums[mid] > target){
// 中間值大於目標值,證明目標值可能在左邊
right = mid;
}
}
return -1;
}
/**
* 左開右閉的方式查詢
*/
public int bs2(int[] nums, int target){
int n = nums.length;
// 搜尋 1 - n 中是否存在
int left = 0;
int right = n;
while(left < right){
int mid = (left + right + 1) / 2;
if (nums[mid - 1] == target){
return mid - 1;
}else if (nums[mid - 1] < target){
left = mid;
}else if (nums[mid - 1] > target){
right = mid - 1;
}
}
return -1;
}
public static void main(String[] args) {
int[] nums = {0, 1, 2, 4, 5, 7, 9};
int target = 5;
BinarySearch bs = new BinarySearch();
int ansPos = bs.customSearch(nums, target);
System.out.println("the pos of target is " + ansPos);
// 這裡我驗證一下,左開右閉的效果
int ans = bs.bs2(nums, target);
System.out.println("" + ans);
}
}