C語言詳細講解二分查找用法
【力扣題號】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的每個元素都將在[-9999, 9999]之間。
注意讀題,數(shù)組為有序數(shù)組,且數(shù)組中無重復(fù)元素,因為一旦有重復(fù)元素,使用二分查找法返回的元素下標(biāo)可能不是唯一的。
在二分查找的過程中,保持不變量,就是在 while 尋找中每一次邊界的處理都要堅持根據(jù)區(qū)間的定義來操作,這就是循環(huán)不變量規(guī)則。
寫二分法,區(qū)間的定義一般為兩種,左閉右閉即 [left, right],或者左閉右開即 [left, right)。
- 二分法第一種寫法
第一種寫法,我們定義 target 是在一個在左閉右閉的區(qū)間里,也就是[left, right] 。因為定義 target 在 [left, right] 區(qū)間,所以有如下兩點:
while (left <= right) 要使用 <= ,因為left == right是有意義的,所以使用 <=
if (nums[middle] > target) ,right 要賦值為 middle - 1,因為當(dāng)前這個 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 是在一個在左閉右開的區(qū)間里,也就是[left, right) ,那么二分法的邊界處理方式則截然不同。
有如下兩點:
while (left < right),這里使用 < ,因為 left == right 在區(qū)間 [left, right) 是沒有意義的
if (nums[middle] > target) ,right 更新為 middle,因為當(dāng)前 nums[middle] 不等于 target,去左區(qū)間繼續(xù)尋找,而尋找區(qū)間是左閉右開區(qū)間,所以 right 更新為 middle,即:下一個查詢區(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) { // 因為left == right的時候,在[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語言詳細講解二分查找用法的文章就介紹到這了,更多相關(guān)C語言 二分查找內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
用C語言實現(xiàn)從文本文件中讀取數(shù)據(jù)后進行排序的功能
這是一個十分可靠的程序,這個程序的查錯能力非常強悍。程序包含了文件操作,歸并排序和字符串輸入等多種技術(shù)。對大家學(xué)習(xí)C語言很有幫助,有需要的一起來看看。2016-08-08vsCode配置import@路徑提示的實現(xiàn)步驟
在導(dǎo)入文件設(shè)置路徑的時候方便了很多,本文主要介紹了vsCode配置import@路徑提示的實現(xiàn)步驟,具有一定的參考價值,感興趣的可以了解一下2023-08-08超詳細VScode調(diào)試教程tasks.json和launch.json的設(shè)置
vscode是一個輕量級的文本編輯器,但是它的擴展插件可以讓他拓展成功能齊全的IDE,這其中就靠的是tasks.json和launch.json的配置,下面這篇文章主要給大家介紹了關(guān)于超詳細VScode調(diào)試教程tasks.json和launch.json設(shè)置的相關(guān)資料,需要的朋友可以參考下2022-10-10