coding ability 展開第五幕(二分查找算法)超詳細!!!!

.在這里插入圖片描述

.

文章目錄

  • 前言
  • 二分查找
  • 搜索插入的位置
    • 思路
  • x的平方根
    • 思路
  • 山脈數組的峰頂索引
    • 思路
  • 尋找旋轉排序數組中的最小值
    • 思路
  • 總結

前言

本專欄上篇博客已經把滑動指針收尾啦
現在還是想到核心——一段連續的區間,有時候加上哈希表用起來很爽
今天我們來學習新的算法知識——二分查找,相信大家都不陌生
二分查找,怎么說呢,清晰了解之后,其實代碼就幾行
話不多說,跟我一起來瞅瞅吧

二分查找

首先我們來學習兩道經典例題,有了例題和板子,才能更好的擴展和延伸,應對不同的場景
二分查找
在這里插入圖片描述
其實乍一看,直接遍歷一遍不就好了嗎,但是今天我們的主題是二分查找
所以這一題來學習一下二分的第一個最簡單的板子
解法一就是暴力循環找目標值
解法二:
在這里插入圖片描述
其實核心就是二段性,只要給的數據有二段性,我們就能用二分
最樸素的就是不斷的找 mid 然后判斷 ,再進到新的區間 ,不斷二分
看看這題代碼,其實大家應該都會寫的,最基礎的二分板子

class Solution 
{
public:int search(vector<int>& nums, int target){int left = 0, right = nums.size() - 1;while(left <= right){int mid = left + (right - left) / 2;if(target > nums[mid])left = mid + 1;else if( target < nums[mid])right = mid - 1;elsereturn mid;}return -1;}
};

可能覺得二分就這么簡單嗎?? 不不不,還有另外兩個板子,會有點麻煩
在排序數組中查找元素的第一個和最后一個位置
在這里插入圖片描述
這題能把另外兩個二分的板子完美詮釋出來,在做這一題之前,我們先來了解兩種情況
前面我們的樸素版本就是 大于 等于 小于 三種情況。
現在我們來想想 左邊區間是小于目標值 右邊區間是大于等于目標值 兩種情況怎么處理
也就是找區間的左端點,如下圖:
在這里插入圖片描述
相比于前面的樸素板子,有很多細節差別
—left 和 right 的更新, 當 x 小于目標值時,那就是左邊區間,這時候left——mid的區間都是不滿足條件的,因為左邊區間都是小于目標值,所以 left 要更新為 mid+1當 x 大于等于目標值時,因為我們右邊區間默認是大于等于目標值的區間,我們的 right 如果更新為 mid - 1,有可能當前的mid就是要找尋的點所以 right 應該更新為 mid
—循環條件 當 left == right 時,就是我們要找的答案,這個時候如果循環條件為 left<=right ,會進入死循環
mid的取值,看下圖,假設就剩下兩個值,目標值是left先用第一種方法 mid 就是 left,這個時候 x >= 目標值所以right == mid剛好left 和 right 相等,找到目標值,如果取用第二種方法取mid為right,這個時候 x >= 目標值,right 和 mid 相等,然后left還是小于right,死循環,所以當我們把區間分成左邊完全小于目標值,右邊大于等于目標值的時候,就用第一種
在這里插入圖片描述
左端點結束了,接下來就是右端點了
也就是左邊區間小于等于目標值,右邊區間完全大于目標值
在這里插入圖片描述
需要注意的細節還是
—left 和 right 的更新 ,當 x > 目標值的時候 right更新為 mid - 1,因為右邊區間都是大于目標值的, 當 x <= 目標值的時候left更新為mid,因為左邊區間小于等于目標值,可能mid的位置就是目標值
—left < right left 不能等于 right
—還是 mid 的取值問題,再來回到這個圖在這里插入圖片描述
我們先使用第一種,當right為目標值時,更新 mid 是剛好為 left,這個時候left更新為mid,right還是大于left,陷入死循環,使用第二種的話,更新mid為rightleft更新為mid也就是right,left和right相等,跳出循環,找到目標值。所以當區間分成左區間小于等于,右區間大于時,用第二種取mid

好了,找左右端點我們都學會了這題,也是能穩穩拿下了
題目要求找到目標值的左右端點,那我們來一次找左端點的操作,再來一次右端點的操作就好啦,話不多說,上代碼

class Solution 
{
public:vector<int> searchRange(vector<int>& nums, int target) {if(nums.size() == 0)return{-1, -1};int begin = 0;int left = 0, right = nums.size() - 1;while(left < right)   //  找左端點{int mid = left + (right - left) / 2;if(nums[mid] < target)left = mid + 1;elseright = mid;}if(nums[left] != target) return {-1, -1};begin = left;right = nums.size() - 1;while(left < right)  //  找右端點{int mid = left + (right - left + 1) / 2;if(nums[mid] > target)right = mid - 1;elseleft = mid;}return {begin, right};}
};

搜索插入的位置

在這里插入圖片描述

思路

這題看來就是左區間小于,又區間大于等于,二段性就分好啦
假設插入的坐標是x,那么x左邊都是小于目標值的,右區間都是大于等于目標值的
我們可以用查詢左端點的板子,直接返回找到的左端點
還有一種特殊情況就是,數據插入在末尾,原本的數據全部小于目標值的,就把這一點處理一下就好了
話不多說,上代碼

class Solution 
{
public:int searchInsert(vector<int>& nums, int target) {int left = 0, right = nums.size() - 1;while(left < right){int mid = left + (right - left) / 2;if(nums[mid] < target)  //  特殊情況,所有數據都比目標值小left = mid + 1;		//	返回right + 1elseright = mid;}if(nums[left] < target)return left + 1;elsereturn right;} 
};

x的平方根

在這里插入圖片描述

思路

本題第一種思路就是暴力枚舉就好了,0-x/2區間一個一個枚舉,挺簡單的思路,就不多贅述了
第二種思路就是二分,我們可以用右端點的板子,設定 i * i <= x為條件,進行二分,最終返回的就是小于等于算數平方根的下標, 話不多說,上代碼

class Solution 
{
public:int mySqrt(int x) {if(x == 0)return 0;long long right = x / 2, left = 1;while(left < right){long long  mid = left + (right - left + 1) / 2; // 查詢右端點取中點處理if(mid * mid > (long long)x)right = mid - 1;elseleft = mid;}return left;        }
};

其實核心就是找到數據的二段性,然后看情況選擇二分查找左端點還是右端點就好啦

山脈數組的峰頂索引

在這里插入圖片描述

思路

題目的意思是找到山脈的頂峰,第一種思路當然就是暴力查找了,找到最大值就行
第二種思路就是我們可以把山脈分成兩份,二段性不就來了嘛,一段單調增,一段單調減
然后根據情況查找左端點或者右端點就好啦
我們把左區間設定為遞增到山頂的區間,右區間就是下山的區間
這個時候應該用我們的查詢右端點的板子,然后我們的判斷條件可以設為 arr[mid] > arr[mid - 1]
話不多說,看代碼

class Solution 
{
public:int peakIndexInMountainArray(vector<int>& arr) {int left = 1, right = arr.size() - 2;while(left < right){int mid = left + (right - left + 1) / 2;if(arr[mid] > arr[mid - 1]) left = mid;elseright = mid - 1;}return left;}
};

當然,也可以用查詢左端點的板子來寫

class Solution 
{
public:int peakIndexInMountainArray(vector<int>& arr) {int left = 1, right = arr.size() - 2;while(left < right){int mid = left + (right - left) / 2;if(arr[mid] > arr[mid + 1]) right = mid;elseleft = mid + 1;}return left;}
};

其實,核心就是找到二段性,然后再找判斷條件

尋找旋轉排序數組中的最小值

在這里插入圖片描述

思路

題目的二段性意思已經寫在臉上了,如圖
在這里插入圖片描述
我們直接設定右端點為 x ,然后上查找左端點的板子,這個x用來判斷區間條件
就是兩步,二段性,區間條件,話不多說,上代碼

class Solution 
{
public:int findMin(vector<int>& nums) {int left = 0, right = nums.size() - 1;int x = nums[right];while(left < right){int mid = left + (right - left) / 2;if(nums[mid] > x) //  當前值大于  x  表示在左區間left = mid + 1;   //  更新leftelseright = mid;}return nums[left];}
};

總結

二分查找是一種高效的搜索算法,核心在于利用數據的二段性將區間不斷二分,快速定位目標。本文通過經典例題解析了三種常見場景的二分應用:

  1. 基本查找:適用于有序數組,通過比較中間值與目標調整區間,時間復雜度O(logN)。
  2. 邊界查找
    • 左邊界:右區間≥目標,循環條件left<right,mid取左中點,更新策略確保不遺漏可能解。
    • 右邊界:左區間≤目標,mid取右中點,避免死循環。
  3. 特殊場景:如山脈數組峰值、旋轉數組最小值,通過分析數據規律(如單調性變化點)構造二段性條件。

關鍵點

  • 循環條件選擇(left<rightleft<=right)。
  • mid計算方式(防止溢出)與邊界更新策略。
  • 處理目標不存在或越界的特殊情況。

掌握二分查找的核心在于理解區間劃分邏輯,靈活選擇模板,結合問題特點設計判斷條件,從而高效解決復雜查找問題

今天的內容就到這里啦,不要走開小編持續更新中~~~

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/898544.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/898544.shtml
英文地址,請注明出處:http://en.pswp.cn/news/898544.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

BEVFormer報錯(預測場景與真值場景的sample_token不匹配)

在運行test.py時報錯&#xff1a; BEVFormer/projects/mmdet3d_plugin/datasets/nuscnes_eval.py&#xff1a; init()函數報錯 assert set(self.pred_boxes.sample_tokens) set(self.gt_boxes.sample_tokens), \"Samples in split doesnt match samples in predictions…

網絡安全威脅與防護措施(下)

8. 惡意軟件&#xff08;Malware&#xff09; **惡意軟件&#xff08;Malware&#xff0c;Malicious Software&#xff09;**是指旨在通過破壞、破壞或未經授權訪問計算機系統、網絡或設備的程序或代碼。惡意軟件通常用于竊取敏感信息、破壞系統、竊取資源、干擾正常操作&…

基于springboot的母嬰商城系統(018)

摘 要 現代經濟快節奏發展以及不斷完善升級的信息化技術&#xff0c;讓傳統數據信息的管理升級為軟件存儲&#xff0c;歸納&#xff0c;集中處理數據信息的管理方式。本母嬰商城系統就是在這樣的大環境下誕生&#xff0c;其可以幫助管理者在短時間內處理完畢龐大的數據信息&am…

shell 腳本搭建apache

#!/bin/bash # Set Apache version to install ## author: yuan# 檢查外網連接 echo "檢查外網連接..." ping www.baidu.com -c 3 > /dev/null 2>&1 if [ $? -eq 0 ]; thenecho "外網通訊良好&#xff01;" elseecho "網絡連接失敗&#x…

使用OBS進行webRTC推流參考

參考騰訊云官方文檔&#xff1a; 云直播 OBS WebRTC 推流_騰訊云 說明非常詳細&#xff0c;分為通過WHIP和OBS插件的形式進行推流。 注意&#xff1a;通過OBS插件的形式進行推流需要使用較低的版本&#xff0c;文檔里有說明&#xff0c;需要仔細閱讀。

Excel 小黑第18套

對應大貓18 .txt 文本文件&#xff0c;點數據 -現有鏈接 -瀏覽更多 &#xff08;文件類型&#xff1a;可以點開文件看是什么分隔的&#xff09; 雙擊修改工作表名稱 為表格添加序號&#xff1a;在數字那修改格式為文本&#xff0c;輸入第一個序號樣式&#xff08;如001&#…

快速入手-基于Django的mysql配置(三)

Django開發操作數據庫更簡單&#xff0c;內部提供了ORM框架。比如mysql&#xff0c;舊版本用pymysql對比較多&#xff0c;新的版本采用mysqlclient。 1、安裝mysql模塊 pip install mysqlclient 2、Django的ORM主要做了兩件事 &#xff08;1&#xff09;CRUD數據庫中的表&am…

【總結篇】java多線程,新建線程有幾種寫法,以及每種寫法的優劣勢

java多線程 新建線程有幾種寫法,以及每種寫法的優劣勢 [1/5]java多線程 新建線程有幾種寫法–繼承Thread類以及他的優劣勢[2/5]java多線程-新建線程有幾種寫法–實現Runnable接口以及他的優劣勢[3/5]java多線程 新建線程有幾種寫法–實現Callable接口結合FutureTask使用以及他的…

基于YOLOv8與ByteTrack的車輛行人多目標檢測與追蹤系統

作者主頁&#xff1a;編程千紙鶴 作者簡介&#xff1a;Java領域優質創作者、CSDN博客專家 、CSDN內容合伙人、掘金特邀作者、阿里云博客專家、51CTO特邀作者、多年架構師設計經驗、多年校企合作經驗&#xff0c;被多個學校常年聘為校外企業導師&#xff0c;指導學生畢業設計并參…

【芯片驗證】面試題·對深度為60的數組進行復雜約束的技巧

朋友發給我的芯片驗證筆試題,覺得很有意思,和大家分享一下。 面試題目 class A中一個長度為60的隨機數組rand int arr[60],如何寫約束使得: 1.每個元素的值都在(0,100]之間,且互不相等; 2.最少有三個元素滿足勾股數要求,比如數組中包含3,4,5三個點; 請以解約束最快…

springmvc中使用interceptor攔截

HandlerInterceptor 是Spring MVC中用于在請求處理之前、之后以及完成之后執行邏輯的接口。它與Servlet的Filter類似&#xff0c;但更加靈活&#xff0c;因為它可以訪問Spring的上下文和模型數據。HandlerInterceptor 常用于日志記錄、權限驗證、性能監控等場景。 ### **1. 創…

【網絡協議】基于UDP的可靠協議:KCP

TCP是為流量設計的&#xff08;每秒內可以傳輸多少KB的數據&#xff09;&#xff0c;講究的是充分利用帶寬。而 KCP是為流速設計的&#xff08;單個數據包從一端發送到一端需要多少時間&#xff09;&#xff0c;以10%-20%帶寬浪費的代價換取了比 TCP快30%-40%的傳輸速度。TCP信…

【論文閱讀】Contrastive Clustering Learning for Multi-Behavior Recommendation

論文地址&#xff1a;Contrastive Clustering Learning for Multi-Behavior Recommendation | ACM Transactions on Information Systems 摘要 近年來&#xff0c;多行為推薦模型取得了顯著成功。然而&#xff0c;許多模型未充分考慮不同行為之間的共性與差異性&#xff0c;以…

藍橋杯2023年第十四屆省賽真題-子矩陣

題目來自DOTCPP&#xff1a; 暴力思路&#xff08;兩個測試點超時&#xff09;&#xff1a; 題目要求我們求出子矩陣的最大值和最小值的乘積&#xff0c;我們可以枚舉矩陣中的所有點&#xff0c;以這個點為其子矩陣的左上頂點&#xff0c;然后判斷一下能不能構成子矩陣。如果可…

centos 磁盤重新分割,將原來/home 下部分空間轉移到 / 根目錄下

上次重裝系統時&#xff0c;不小心將一半磁盤放在了 /home 下面&#xff0c;運行一段時間后&#xff0c;發現/home 空間沒有怎么用&#xff0c;反而是/ 目錄報警說磁盤用完了&#xff0c;準備將 /home下的空間分一部分給主目錄 / 先查看下 空間分布情況 df -lh 可以看到&…

【C#語言】C#同步與異步編程深度解析:讓程序學會“一心多用“

文章目錄 ?前言?一、同步編程&#xff1a;單線程的線性世界&#x1f31f;1、尋找合適的對象?1) &#x1f31f;7、設計應支持變化 ?二、異步編程&#xff1a;多任務的協奏曲?三、async/await工作原理揭秘?四、最佳實踐與性能陷阱?五、異步編程適用場景?六、性能對比實測…

Redis命令詳解--集合

Redis set 是string類型的無序集合。集合成員是唯一的&#xff0c;這就意味著集合中不能出現重復的數據&#xff0c;常用命令&#xff1a; SADD key member1 [member2...] 向集合添加一個或多個成員 SREM key member1 [member2...] 移除集合中一個或多個成員 SMEMBERS key 獲…

學習筆記 ASP.NET Core Web API 8.0部署到iis

一.修改配置文件 修改Program.cs配置文件將 if (app.Environment.IsDevelopment()) {app.UseSwagger();app.UseSwaggerUI(); }修改為 app.UseSwagger(); app.UseSwaggerUI(); 二.安裝ASP.NET Core Runtime 8.0.14 文件位置https://dotnet.microsoft.com/en-us/download/do…

配置 VSCode 的 C# 開發環境

1. 安裝必要的依賴 1.1 VSCode 擴展 安裝 C# 相關插件&#xff08;如 C#、C# Extensions 等&#xff09;。 1.2 .NET SDK 下載地址&#xff1a;.NET SDK 下載頁面 1.3 安裝檢測 在命令行輸入以下命令&#xff0c;如果正確返回了版本號&#xff0c;則表示 .NET SDK 安裝成…

從零搭建微服務項目Pro(第6-1章——Spring Security+JWT實現用戶鑒權訪問與token刷新)

前言&#xff1a; 在現代的微服務架構中&#xff0c;用戶鑒權和訪問控制是非常重要的一部分。Spring Security 是 Spring 生態中用于處理安全性的強大框架&#xff0c;而 JWT&#xff08;JSON Web Token&#xff09;則是一種輕量級的、自包含的令牌機制&#xff0c;廣泛用于分…