C語言詳細(xì)講解二分查找用法
【力扣題號】704.二分查找 力扣題目鏈接
示例 1:
輸入: nums = [-1,0,3,5,9,12], target = 9
輸出: 4
解釋: 9 出現(xiàn)在 nums 中并且下標(biāo)為 4
示例 2:
輸入: nums = [-1,0,3,5,9,12], target = 2
輸出: -1
解釋: 2 不存在 nums 中因此返回 -1
提示:
- 你可以假設(shè) nums中的所有元素是不重復(fù)的。
- n將在[1, 10000]之間。
- nums的每個(gè)元素都將在[-9999, 9999]之間。
注意讀題,數(shù)組為有序數(shù)組,且數(shù)組中無重復(fù)元素,因?yàn)橐坏┯兄貜?fù)元素,使用二分查找法返回的元素下標(biāo)可能不是唯一的。
在二分查找的過程中,保持不變量,就是在 while 尋找中每一次邊界的處理都要堅(jiān)持根據(jù)區(qū)間的定義來操作,這就是循環(huán)不變量規(guī)則。
寫二分法,區(qū)間的定義一般為兩種,左閉右閉即 [left, right],或者左閉右開即 [left, right)。
- 二分法第一種寫法
第一種寫法,我們定義 target 是在一個(gè)在左閉右閉的區(qū)間里,也就是[left, right] 。因?yàn)槎x target 在 [left, right] 區(qū)間,所以有如下兩點(diǎn):
while (left <= right) 要使用 <= ,因?yàn)閘eft == right是有意義的,所以使用 <=
if (nums[middle] > target) ,right 要賦值為 middle - 1,因?yàn)楫?dāng)前這個(gè) nums[middle] 一定不是 target ,那么接下來要查找的左區(qū)間結(jié)束下標(biāo)位置就是 middle - 1
// 版本一
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1; // 定義target在左閉右閉的區(qū)間里,[left, right]
while (left <= right) { // 當(dāng)left==right,區(qū)間[left, right]依然有效,所以用 <=
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] > target) {
right = middle - 1; // target 在左區(qū)間,所以[left, middle - 1]
} else if (nums[middle] < target) {
left = middle + 1; // target 在右區(qū)間,所以[middle + 1, right]
} else { // nums[middle] == target
return middle; // 數(shù)組中找到目標(biāo)值,直接返回下標(biāo)
}
}
// 未找到目標(biāo)值
return -1;
}
};- 二分法第二種寫法
如果說定義 target 是在一個(gè)在左閉右開的區(qū)間里,也就是[left, right) ,那么二分法的邊界處理方式則截然不同。
有如下兩點(diǎn):
while (left < right),這里使用 < ,因?yàn)?left == right 在區(qū)間 [left, right) 是沒有意義的
if (nums[middle] > target) ,right 更新為 middle,因?yàn)楫?dāng)前 nums[middle] 不等于 target,去左區(qū)間繼續(xù)尋找,而尋找區(qū)間是左閉右開區(qū)間,所以 right 更新為 middle,即:下一個(gè)查詢區(qū)間不會去比較 nums[middle]
// 版本二
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size(); // 定義target在左閉右開的區(qū)間里,即:[left, right)
while (left < right) { // 因?yàn)閘eft == right的時(shí)候,在[left, right)是無效的空間,所以使用 <
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle; // target 在左區(qū)間,在[left, middle)中
} else if (nums[middle] < target) {
left = middle + 1; // target 在右區(qū)間,在[middle + 1, right)中
} else { // nums[middle] == target
return middle; // 數(shù)組中找到目標(biāo)值,直接返回下標(biāo)
}
}
// 未找到目標(biāo)值
return -1;
}
};通過以上兩種方法,要注意它們不同的地方:
① right 的初始值不一樣
② 左右區(qū)間的更新值的差別
參考:《代碼隨想錄》
到此這篇關(guān)于C語言詳細(xì)講解二分查找用法的文章就介紹到這了,更多相關(guān)C語言 二分查找內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言詳盡圖解函數(shù)棧幀的創(chuàng)建和銷毀實(shí)現(xiàn)
我們知道c語言中函數(shù)都是被調(diào)用的,main函數(shù)里面能調(diào)用其他函數(shù),其實(shí)main函數(shù)也是被別的函數(shù)調(diào)用的,下面通過本文給大家分享c語言函數(shù)棧幀的創(chuàng)建和銷毀過程,一起看看吧2022-05-05
C++動態(tài)規(guī)劃中關(guān)于背包問題講解
可能有些讀者有接觸過動態(tài)規(guī)劃,可能也有一些讀者以前完全不知道動態(tài)規(guī)劃這個(gè)東西,別擔(dān)心,我這篇文章會為讀者做一個(gè)入門,好讓讀者掌握這個(gè)重要的知識點(diǎn)2023-03-03
C語言項(xiàng)目爬樓梯的兩種實(shí)現(xiàn)方法參考
今天小編就為大家分享一篇關(guān)于C語言項(xiàng)目爬樓梯的兩種實(shí)現(xiàn)方法參考,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02
C++ map 根據(jù)value找key的實(shí)現(xiàn)
今天小編就為大家分享一篇C++ map 根據(jù)value找key的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-12-12
C/C++中一次性執(zhí)行多個(gè)DOS命令的實(shí)現(xiàn)思路
在C語言中執(zhí)行DOS命令的方法很多,在這就不一給大家一一介紹了,本文重點(diǎn)給大家介紹C/C++中一次性執(zhí)行多個(gè)DOS命令的實(shí)現(xiàn)思路,需要的朋友參考下2017-12-12
詳解C語言中sizeof如何在自定義函數(shù)中正常工作
在main函數(shù)中,sizeof是可以正常工作的,但是在自定義函數(shù)中就不可以了。所以本文將為大家詳細(xì)講解一下如何解決這一問題,感興趣的可以了解一下2022-05-05
C++中的std::funture和std::promise實(shí)例詳解
在線程池中獲取線程執(zhí)行函數(shù)的返回值時(shí),通常使用 std::future 而不是 std::promise 來傳遞返回值,這篇文章主要介紹了C++中的std::funture和std::promise實(shí)例詳解,需要的朋友可以參考下2024-05-05

