優選算法系列(3.二分查找 )

目錄

一.二分查找(easy)

題目鏈接:704. 二分查找 - 力扣(LeetCode)

解法:

代碼:

?二.在排序數組中查找元素的第?個和最后?個位置(medium)

題目鏈接:34. 在排序數組中查找元素的第一個和最后一個位置 - 力扣(LeetCode)

解法:

代碼:

二分模板:

?三.搜索插入位置(easy)

題目鏈接:35. 搜索插入位置 - 力扣(LeetCode)

解法:

代碼:

?四.?x 的平方根(easy)

題目鏈接:69. x 的平方根 - 力扣(LeetCode)

解法:

代碼:

五:山峰數組的峰頂(easy)

題目鏈接:852. 山脈數組的峰頂索引 - 力扣(LeetCode)

解法:

代碼:

六:尋找峰值(medium)

題目鏈接:162. 尋找峰值 - 力扣(LeetCode)

解法:

代碼:

七:搜索旋轉排序數組中的最小值(medium)

題目鏈接:153. 尋找旋轉排序數組中的最小值 - 力扣(LeetCode)

解法:

代碼:

八:0?n-1 中缺失的數字(easy)

題目鏈接:LCR 173. 點名 - 力扣(LeetCode)

解法:

代碼:


一.二分查找(easy)

題目鏈接:704. 二分查找 - 力扣(LeetCode)

?

解法:

暴力解法無非就是從左到右枚舉,復雜度O(N)

但是這個數組是一個升序的,如果隨便取一個數比他小,那么所取得數左邊的數都比目標小這樣就只需要向他右邊找,如果比目標值大也一樣那么去它左邊找。

  • 定義 left right 指針,分別指向數組的左右區間。
  • 找到待查找區間的中間點 mid ,找到之后分三種情況討論:
  1. arr[mid] == target 說明正好找到,返回 mid 的值;
  2. arr[mid] > target 說明 [mid, right] 這段區間都是?于 target 的,因此舍去右邊區間,在左邊 [left, mid -1] 的區間繼續查找,即讓 right = mid - 1 ,然后重復 2 過程;
  3. arr[mid] < target 說明 [left, mid] 這段區間的值都是?于 target 的,因此舍去左邊區間,在右邊 [mid + 1, right] 區間繼續查找,即讓 left = mid +1 ,然后重復 2 過程;
  • left right 錯開時,說明整個區間都沒有這個數,返回 -1

代碼:

?

?二.在排序數組中查找元素的第?個和最后?個位置(medium)

題目鏈接:34. 在排序數組中查找元素的第一個和最后一個位置 - 力扣(LeetCode)

解法:

暴力查找O(N)

?

?二分:

?的還是?分思想,就是根據數據的性質,在某種判斷條件下將區間?分為?,然后舍去其中?個區間,然后再另?個區間內查找; 方便敘述,? x 表示該元素, resLeft 表示 左邊界, resRight表示 右邊界。

查找左端點

我們注意到以左邊界劃分的兩個區間的特點:
  • 左邊區間 [left, resLeft - 1] 都是?于 x 的;
  • 右邊區間(包括左邊界) [resLeft, right] 都是?于等于 x 的;
因此,關于 mid 的落點,我們可以分為下面兩種情況:
  • 當我們的 mid 落在 [left, resLeft - 1] 區間的時候,也就是 arr[mid] < target 。說明 [left, mid] 都是可以舍去的,此時更新 left mid + 1 的位置,繼續在 [mid + 1, right] 上尋找左邊界;
  • mid 落在 [resLeft right] 的區間的時候,也就是 arr[mid] >= target 。說明 [mid + 1, right] (因為 mid 可能是最終結果,不能舍去)是可以舍去的,此時更新 right mid 的位置,繼續在 [left, mid] 上尋找左邊界;
由此,就可以通過?分,來快速尋找左邊界;
注意:這?找中間元素需要向下取整。
因為后續移動左右指針的時候:
  • 左指針: left = mid + 1 ,是會向后移動的,因此區間是會縮?的;
  • 右指針: right = mid ,可能會原地踏步(?如:如果向上取整的話,如果剩下 1,2 兩個元素, left == 1 right == 2 mid == 2 。更新區間之后, leftrightmid 的值沒有改變,就會陷?死循環)。
因此?定要注意,當 right = mid 的時候,要向下取整。

循環條件:

?求中點操作:

?查找右端點

? resRight 表示右邊界;
我們注意到右邊界的特點:
  • 左邊區間 (包括右邊界) [left, resRight] 都是?于等于 x 的;
  • 右邊區間 [resRight+ 1, right] 都是?于 x 的;
因此,關于 mid 的落點,我們可以分為下面兩種情況:
  • 當我們的 mid 落在 [left, resRight] 區間的時候,說明 [left, mid - 1]( mid 不可以舍去,因為有可能是最終結果) 都是可以舍去的,此時更新 left mid的位置;
  • mid 落在 [resRight+ 1, right] 的區間的時候,說明 [mid, right] 內的元素是可以舍去的,此時更新 right mid - 1 的位置;
由此,就可以通過?分,來快速尋找右邊界;
注意:這?找中間元素需要向上取整
因為后續移動左右指針的時候:
  • 左指針: left = mid ,可能會原地踏步(?如:如果向下取整的話,如果剩下 1,2 兩個元素, left == 1 right == 2mid == 1 。更新區間之后, leftrightmid 的值沒有改變,就會陷?死循環)。
  • 右指針: right = mid - 1 ,是會向前移動的,因此區間是會縮小的;
因此?定要注意,當 right = mid 的時候,要向下取整。

代碼:

?C++:

java:

二分模板:

?三.搜索插入位置(easy)

題目鏈接:35. 搜索插入位置 - 力扣(LeetCode)

解法:

分析插入位置左右兩側區間上元素的特點:

  1. [left, index - 1] 內的所有元素均是小于 target 的;
  2. [index, right] 內的所有元素均是大于等于 target 的。

left 為本輪查詢的左邊界, right 為本輪查詢的右邊界。根據 mid 位置元素的信息,分析下?輪查詢的區間:

  1. nums[mid] >= target 時,說明 mid 落在了 [index, right] 區間上,mid 左邊包括 mid 本?,可能是最終結果,所以我們接下來查找的區間在 [left,mid] 上。因此,更新 right mid 位置,繼續查找。
  2. nums[mid] < target 時,說明 mid 落在了 [left, index - 1] 區間上,mid 右邊但不包括 mid 本?,可能是最終結果,所以我們接下來查找的區間在 [mid+ 1, right] 上。因此,更新 left mid + 1 的位置,繼續查找。

直到我們的查找區間的?度變為 1 ,也就是 left == right 的時候, left 或者right 所在的位置就是我們要找的結果。

代碼:

C++:

java:

?

?四.?x 的平方根(easy)

題目鏈接:69. x 的平方根 - 力扣(LeetCode)

解法:

解法?(暴力查找):
依次枚舉 [0, x] 之間的所有數 i
(這?沒有必要研究是否枚舉到 x / 2 還是 x / 2 + 1 。因為我們找到結果之后直接就返回了,往后的情況就不會再判斷。反而研究枚舉區間,既耽誤時間,又可能出錯)
  • 如果 i * i == x ,直接返回 x
  • 如果 i * i > x ,說明之前的?個數是結果,返回 i - 1
由于 i * i 可能超過 int 的最?值,因此使? long long 類型
解法二(二分查找算法):
x 的平方根的最終結果為 index
分析 index 左右兩次數據的特點:
  1. [0, index] 之間的元素,平方之后都是小于等于 x 的;
  2. [index + 1, x] 之間的元素,平方之后都是大于 x 的。
因此可以使?二分查找算法。

代碼:

C++:

java:

?

五:山峰數組的峰頂(easy)

題目鏈接:852. 山脈數組的峰頂索引 - 力扣(LeetCode)

解法:

暴力求解:
峰頂的特點:?兩側的元素都要?。
因此,我們可以遍歷數組內的每?個元素,找到某?個元素比兩邊的元素大即可。
二分:
分析峰頂位置的數據特點,以及?峰兩旁的數據的特點:
  1. 峰頂數據特點: arr[i] > arr[i - 1] && arr[i] > arr[i + 1]
  2. 峰頂左邊的數據特點: arr[i] > arr[i - 1] && arr[i] < arr[i + 1] ,也就是呈現上升趨勢;
  3. 峰頂右邊數據的特點: arr[i] < arr[i - 1] && arr[i] > arr[i + 1] ,也就是呈現下降趨勢。
? 因此,根據 mid 位置的信息,我們可以分為下面三種情況:
  1. 如果 mid 位置呈現上升趨勢,說明我們接下來要在 [mid + 1, right] 區間繼續搜索;
  2. 如果 mid 位置呈現下降趨勢,說明我們接下來要在 [left, mid - 1] 區間搜索;
  3. 如果 mid 位置就是山峰,直接返回結果。

代碼:

C++:

java:

六:尋找峰值(medium)

題目鏈接:162. 尋找峰值 - 力扣(LeetCode)

解法:

和上題沒什么區別。。。
任取?個點 i ,與下?個點 i + 1 ,會有如下兩種情況:
  • arr[i] > arr[i + 1] :此時「左側區域」?定會存在?峰(因為最左側是負無窮),那么我們可以去左側去尋找結果;
  • arr[i] < arr[i + 1] :此時「右側區域」?定會存在山峰(因為最右側是負無窮),那么我們可以去右側去尋找結果。
當找到「二段性」的時候,就可以嘗試?「二分查找」算法來解決問題。

代碼:

C++:

java:

七:搜索旋轉排序數組中的最小值(medium)

題目鏈接:153. 尋找旋轉排序數組中的最小值 - 力扣(LeetCode)

解法:

題目我們可以知道原本這個原本是一個升序數組,也即是

這個樣子的一個數組,那么所謂的“旋轉n次數”也就是所把最大的(數組最后)那幾個值拿到前面去。

通過圖像我們可以發現, [A B] 區間內的點都是嚴格?于 D 點的值的, C 點的值是嚴格小于 D 點的值的。但是當 [C D] 區間只有?個元素的時候, C 點的值是可能等于 D 點的值的。
因此,初始化左右兩個指針 left right
然后根據 mid 的落點,我們可以這樣劃分下?次查詢的區間:
  1. mid [AB] 區間的時候,也就是 mid 位置的值嚴格大于 D 點的值,下?次查詢區間在 [mid + 1right] 上;
  2. mid [CD] 區間的時候,也就是 mid 位置的值嚴格小于等于 D 點的值,下次查詢區間在 [leftmid] 上。
當區間長度變成 1 的時候,就是我們要找的結果。

代碼:

C++:

java:

八:0?n-1 中缺失的數字(easy)

題目鏈接:LCR 173. 點名 - 力扣(LeetCode)

解法:

關于這道題中,時間復雜度為 O(N) 的解法有很多種,而且也是比較好想的,這里就不再贅述。本題只講解?個最優的?分法,來解決這個問題。
在這個升序的數組中,我們發現:
  • 在第?個缺失位置的左邊,數組內的元素都是與數組的下標相等的;
  • 在第?個缺失位置的右邊,數組內的元素與數組下標是不相等的。
因此,我們可以利用這個「二段性」,來使?「二分查找」算法。

代碼:

C++:

java:

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

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

相關文章

DAY36貪心算法Ⅴ

56. 合并區間 - 力扣&#xff08;LeetCode&#xff09; class Solution { static bool cmp(vector<int>&a,vector<int>&b){return a[0] < b[0]; } public:vector<vector<int>> merge(vector<vector<int>>& intervals) {so…

阿里云服務器部署 五 Nginx + springboot

Nginx的部分配置 1. 基礎容災配置&#xff08;被動健康檢查&#xff09; 在 upstream 塊中&#xff0c;通過 max_fails 和 fail_timeout 參數定義故障轉移規則&#xff1a; 在 upstream 塊中&#xff0c;通過 max_fails 和 fail_timeout 參數定義故障轉移規則&#xff1a;…

基于大模型的下頜前突畸形預測及治療方案研究報告

目錄 一、引言 1.1 研究背景 1.2 研究目的 1.3 研究意義 二、大模型技術原理與應用現狀 2.1 大模型的基本原理 2.2 在醫療領域的應用案例 2.3 在下頜前突畸形研究中的可行性分析 三、下頜前突畸形概述 3.1 定義與分類 3.2 流行病學特征 3.3 病因與發病機制 3.4 對…

接口自動化測試框架詳解

&#x1f345; 點擊文末小卡片&#xff0c;免費獲取軟件測試全套資料&#xff0c;資料在手&#xff0c;漲薪更快 接口自動化測試是指通過編寫程序來模擬用戶的行為&#xff0c;對接口進行自動化測試。Python是一種流行的編程語言&#xff0c;它在接口自動化測試中得到了廣泛…

Day11 動態規劃入門

動態規劃 就是 : 給定一個問題&#xff0c;我們把它拆成一個個子問題&#xff0c;直到子問題可以直接解決。然后把子問題的答案保存起來&#xff0c;以減少重復計算。再根據子問題答案反推&#xff0c;得出原問題解的一種方法. 記憶化搜索 暴力dfs 記錄答案 動態規劃入門思…

[AI速讀]用持續集成(CI)優化芯片驗證環境:Jenkins與EDA工具的實戰指南

在芯片驗證中,回歸測試(Regression Test)是確保設計穩定性的關鍵步驟。但隨著設計復雜度增加,手動管理海量測試用例、分析日志和覆蓋率數據變得異常耗時。本文將介紹如何利用持續集成(CI)工具Jenkins,結合EDA驗證環境(如Cadence vManager),實現自動化測試與結果分析,…

深度解析:JavaScript變量聲明的演變與核心差異(var/let/隱式聲明)

深度解析&#xff1a;JavaScript變量聲明的演變與核心差異&#xff08;var/let/隱式聲明&#xff09; 一、JavaScript變量聲明的演進史 JavaScript的變量聲明機制經歷了三個階段演進&#xff1a; 原始階段&#xff08;ES5及之前&#xff09;&#xff1a;僅 var 聲明 隱式全局…

第2.1節:AWK腳本結構

1 第2.1節&#xff1a;AWK腳本結構 1.1 第1個awk腳本 假設有如下的數據待處理&#xff0c;需要將第2列提取出來&#xff1a; #, 名稱, 大小, 類型, 修改, 屬性 1, COMMIT_EDITMSG, 331 bytes, 文件, 24/09/16 08:42:19, -a----- 2, config, …

Win NAS 分享功能:精準、安全的內容共享

WinNAS 不僅是一款強大的 NAS服務&#xff0c;還通過耘想存儲 APP 提供了便捷的內容分享功能。無論是與個人、群聊、朋友圈還是公眾分享文件&#xff0c;WinNAS 都配備了嚴格的權限管理機制&#xff0c;確保您的數據安全且精準地傳遞給目標對象。以下是 WinNAS 分享功能的詳細介…

C# 項目06-計算程序運行時間

實現需求 記錄程序運行時間&#xff0c;當程序退出后&#xff0c;保存程序運行時間&#xff0c;等下次程序再次啟動時&#xff0c;繼續記錄運行時間 運行環境 Visual Studio 2022 知識點 TimeSpan 表示時間間隔。兩個日期之間的差異的 TimeSpan 對象 TimeSpan P_TimeSpa…

網絡華為HCIA+HCIP NFV

目錄 NFV關鍵技術&#xff1a;虛擬化 NFV關鍵技術&#xff1a;云化 NFV架構 NFV標準架構 ?編輯 NFV架構功能模塊 NFV架構接口 NFV關鍵技術&#xff1a;虛擬化 在NFV的道路上&#xff0c;虛擬化是基礎&#xff0c;云化是關鍵。傳統電信網絡中&#xff0c;各個網元都是…

SpringBoot實現異步調用的方法

在Java中使用Spring Boot實現異步請求和異步調用是一個常見的需求&#xff0c;可以提高應用程序的性能和響應能力。以下是實現這兩種異步操作的基本方法&#xff1a; 一、異步請求&#xff08;Asynchronous Request&#xff09; 異步請求允許客戶端發送請求后立即返回&#x…

xwiki自定義認證實現單點登錄

xwiki支持自定義認證 繼承XWikiAuthServiceImpl類后將類配置到WEB-INFO下xwiki.cfg的xwiki.authentication.authclass屬性上開啟自定義認證。 官方文檔&#xff1a;https://www.xwiki.org/xwiki/bin/view/Documentation/AdminGuide/Authentication/ 官方自定義認證的示例&#…

使用vite新建vue3項目 以及elementui的使用 vite組件問題

項目創建 在創建項目之前我們應該在終端中輸入 node -v 和 npm -v 只有它們都能正常查看版本號才說明我們之前是已經安裝完成的。 接下來我們在合適的目錄下輸入npm create vitelatest 它會要求你輸入項目的名稱&#xff0c;這個名稱和我們之前通過cil創建的命名規則一樣。…

音頻錄制小妙招-自制工具-借助瀏覽器錄一段單聲道16000采樣率wav格式音頻

先看效果 1、打開頁面 2、點擊開始錄音&#xff0c;彈出權限提示&#xff0c;點擊“僅這次訪問時允許” 3、錄完后&#xff0c;點擊停止 4、文件自動下載到默認目錄 上代碼 js 部分 document.addEventListener(DOMContentLoaded, () > {const startBtn document.getEleme…

Mysql-經典實戰案例(10):如何用PT-Archiver完成大表的自動歸檔

真實痛點&#xff1a;電商訂單表存儲優化場景 現狀分析 某電商平臺訂單表&#xff08;order_info&#xff09;每月新增500萬條記錄 主庫&#xff1a;高頻讀寫&#xff0c;SSD存儲&#xff08;空間告急&#xff09;歷史庫&#xff1a;HDD存儲&#xff0c;只讀查詢 優化目標 …

CUDA編程面試高頻30題

1. 什么是CUDA&#xff1f;它與GPU的關系是什么&#xff1f; 答: CUDA&#xff08;Compute Unified Device Architecture&#xff09;是由NVIDIA開發的一種并行計算平臺和應用程序接口模型。它允許開發者利用NVIDIA GPU進行通用計算任務&#xff0c;而不僅僅是圖形渲染。CUDA提…

數學建模 繪圖 圖表 可視化(3)

文章目錄 前言二維散點圖系列坐標圖數據分布特征&#xff0c;Q-Q、P-P圖分類圖一般的曲線圖峰巒圖總結參考資料 前言 承接上期 數學建模 繪圖 圖表 可視化&#xff08;1&#xff09;的總體描述&#xff0c;這期我們繼續跟隨《Python 數據可視化之美 專業圖表繪制指南》步伐來學…

【數據結構】棧(Stack)、隊列(Queue)、雙端隊列(Deque) —— 有碼有圖有真相

目錄 棧和隊列 1. 棧&#xff08;Stack&#xff09; 1.1 概念 1.2 棧的使用&#xff08;原始方法&#xff09; 1.3 棧的模擬實現 【小結】 2. 棧的應用場景 1、改變元素的序列 2、將遞歸轉化為循環 3、逆波蘭表達式求值 4、括號匹配 5、出棧入棧次序匹配 6、最小棧…

【強化學習】Reward Model(獎勵模型)詳細介紹

&#x1f4e2;本篇文章是博主強化學習&#xff08;RL&#xff09;領域學習時&#xff0c;用于個人學習、研究或者欣賞使用&#xff0c;并基于博主對相關等領域的一些理解而記錄的學習摘錄和筆記&#xff0c;若有不當和侵權之處&#xff0c;指出后將會立即改正&#xff0c;還望諒…