二分查找算法
1 Java算法篇之二分查找算法
1.1 什麼是二分查找算法?
- 算法定義
二分查找算法又叫折半查找算法, 是一種基於比較目標值和數組中間元素的教科書式算
- 使用條件
待查找的數組必須是有順序的
- 複雜度
空間複雜度:O(1)
- 時間複雜度最好情況:O(1)
- 時間複雜度最壞情況:O(LogN) 一般默認指這種。
注意:
可能也聽過下面這種說法:
它們兩個其實是等價的,log2n 的意思是以2爲底數,然後n.
- 算法規則
- 如果目標值等於中間元素,則找到目標值。
- 如果目標值較小,繼續在左側搜索。
- 如果目標值較大,則繼續在右側搜索。
1.2 二分查找算法分析
LeetCode最佳算法解析,請移步二分查找細節詳解,順便賦詩一首
- 初始化指針 left = 0, right = n - 1。
- 當 left <= right:
- 比較中間元素 nums[pivot] 和目標值 target 。
- 如果 target = nums[pivot],返回 pivot。
- 如果 target < nums[pivot],則在左側繼續搜索 right = pivot - 1。
- 如果 target > nums[pivot],則在右側繼續搜索 left = pivot + 1。
1.3 Solution
1.3.1 LeetCode 官方解法
LeetCode 官方二分法解法
class Solution {
public int search(int[] nums, int target) {
int pivot, left = 0, right = nums.length - 1;
while (left <= right) {
pivot = left + (right - left) / 2;
if (nums[pivot] == target) return pivot;
if (target < nums[pivot]) right = pivot - 1;
else left = pivot + 1;
}
return -1;
}
}
作者:LeetCode
鏈接:https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-by-leetcode/
來源:力扣(LeetCode) 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
1.3.2 最佳二分法查找Solution
給大家講個笑話樂呵一下:
- 有一天阿東到圖書館借了 N本書,出圖書館的時候,警報響了,於是保安把阿東攔下,要檢查一下哪本書沒有登記出借。阿東正準備把每一本書在報警器下過一下,以找出引發警報的書,但是保安露出不屑的眼神:你連二分查找都不會嗎?於是保安把書分成兩堆,讓第一堆過一下報警器,報警器響;於是再把這堆書分成兩堆……
- 最終,檢測了 logN 次之後,保安成功的找到了那本引起警報的書,露出了得意和嘲諷的笑容。於是阿東揹着剩下的書走了。
- 從此,圖書館丟了 N - 1 本書。
事故現場還原:
數組下標:0 1 2 3 4
存儲內容:1 2 2 2 3
比如說給你有序數組 nums = [1,2,2,2,3],target 爲 2,上面算法返回的索引是 2,沒錯。但是如果我想得到 target 的左側邊界,即索引 1,或者我想得到 target 的右側邊界,即索引 3,這樣的話此算法是無法處理的。
解決上述需求,完整算法如下:
保安用的基礎二分法算法如下:
//和官方的Leetcode 算法一致
//基礎二分查找算法
int binary_search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
// 搜索區間變爲 [mid+1, right]
left = mid + 1;
} else if (nums[mid] > target) {
// 搜索區間變爲 [left, mid-1]
right = mid - 1;
} else if(nums[mid] == target) {
// 直接返回
return mid;
}
}
// 直接返回
return -1;
}
左側邊界二分法算法如下:
//左側邊界查找算法
int left_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
// 別返回,收縮左側邊界
right = mid - 1;
}
}
// 最後要檢查 left 越界的情況
if (left >= nums.length || nums[left] != target){
return -1;
}
return left;
}
右側邊界二分法算法如下:
//右側邊界查詢算法
int right_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
// 別返回,收縮右側邊界
left = mid + 1;
}
}
// 最後要檢查 right 越界的情況
if (right < 0 || nums[right] != target){
return -1;
}
return right;
}
作者:labuladong
鏈接:https://leetcode-cn.com/problems/binary-search/solution/er-fen-cha-zhao-xiang-jie-by-labuladong/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
本篇完~