LeetCode-刷題記錄-二分法合集(本篇blog會持續更新哦~)

一、二分查找概述

二分查找(Binary Search)是一種高效的查找算法,適用于有序數組或列表。(但其實只要滿足二段性,就可以使用二分法,本篇博客后面博主會持續更新一些題,來破除一下人們對“只有有序才能二分”的誤解。)

在這里插入圖片描述

二分通過反復將查找范圍分為兩半,并根據目標值與中間元素的大小關系來確定下一步查找的方向,從而快速定位目標值的位置。

二、二分法代碼實現

三、二分法習題合集

1.LeetCode 35 搜索插入位置

在這里插入圖片描述
在這里插入圖片描述

  • 解法

在這里插入圖片描述

public static int searchInsert(int[] nums, int target) {int left = 0, right = nums.length - 1;// 使用循環來查找目標值或確定插入位置while (left <= right) {int mid = left + (right - left) / 2; // 計算中間位置,避免整數溢出問題if (nums[mid] > target) {right = mid - 1; // 如果中間值大于目標值,縮小搜索范圍至左半部分} else if (nums[mid] < target) {left = mid + 1; // 如果中間值小于目標值,縮小搜索范圍至右半部分} else {return mid; // 找到目標值,直接返回索引}}// 循環結束時,left 指向應該插入的位置return left;
}
  • 這里博主解釋一下為什么最后返回left(debug走一下流程或者在草稿紙上畫一畫其實就很容易看出來啦~)。

函數 searchInsert 的目標是在給定的有序數組 nums 中查找目標值 target 的插入位置(如果目標值不存在于數組中)。

如果數組中存在目標值,則返回目標值的索引;如果不存在,則返回應該插入的位置索引,使得插入后數組依然保持有序。

插入位置保持有序性

  • 返回 left 而不是 right 是因為當循環結束時,left 恰好指向比 target 大的第一個元素的位置,或者數組的末尾位置(如果 target 大于數組中的所有元素),這正是目標值應該插入的位置,可以保持數組的有序性。

2.LeetCode 69 x的平方

在這里插入圖片描述

  • 解法

在這里插入圖片描述

public static int mySqrt(int x) {if (x == 0 || x == 1) return x;int left = 0, right = x;int ans = 0;while (left <= right) {int mid = left + (right - left) / 2;//防止越界~因為 mid*mid 數值過大 int可能會越界 或者 強轉一下也可——(long)mid*midif (mid < x / mid) { //如果這個整數的平方 嚴格小于 輸入整數,那么這個整數 可能 是我們要找的那個數(重點理解這句話)。ans = mid;//所以我們更新答案left = mid + 1;} else if (mid > x / mid) { //如果這個整數的平方 嚴格大于 輸入整數,那么這個整數  肯定不是  我們要找的那個數;right = mid - 1;} else { //如果這個整數的平方 恰好等于 輸入整數,那么我們就找到了這個整數;return mid;}}return ans;}

3.LeetCode 367 有效的完全平方數

在這里插入圖片描述

  • 解法

在這里插入圖片描述

public static boolean isPerfectSquare(int num) {int left = 0, right = num;// 使用二分查找來確定是否為完全平方數while (left <= right) {int mid = left + (right - left) / 2; // 計算中間值,避免整數溢出問題if ((long) mid * mid < num) {left = mid + 1; // 如果 mid 的平方小于 num,說明目標值在右半部分,縮小搜索范圍至右半部分} else if ((long) mid * mid > num) {right = mid - 1; // 如果 mid 的平方大于 num,說明目標值在左半部分,縮小搜索范圍至左半部分} else {return true; // 如果 mid 的平方等于 num,直接返回 true,表示找到完全平方數}}// 循環結束時,未找到完全平方數,返回 falsereturn false;
}

4.LeetCode 34 在排序數組查找元素的第一個和最后一個位置

在這里插入圖片描述

  • 解法

本題拆分成兩個函數,分別處理較好,不過這個對處理二分的熟練度要求還挺高,比如說left<=right 還是left<right以及左右指針什么時候該怎么移動都有講究,一個小細節不對的話就得不到正確的答案。

大概的二分的模版大家都知道,區別就在于具體問題的邊界問題,是需要自己思考的。

建議有電腦的小伙伴可以debug走一下流程 ,可以看出來左右指針怎么移動的,慢慢調試;或者在紙上畫一畫,看一看自己寫的二分是怎么個流程~


在這里插入圖片描述

public static int[] searchRange(int[] nums, int target) {int[] ans = {-1, -1};// 特殊情況處理:數組為空,或者目標值不在數組范圍內if (nums.length == 0 || nums[0] > target || nums[nums.length - 1] < target) return ans;// 查找第一次出現的位置int first = findFirst(nums, target);if (first == -1) return ans; // 如果找不到目標值,返回初始的{-1, -1}ans[0] = first;// 查找最后一次出現的位置ans[1] = findLast(nums, target);return ans;
}// 找到元素第一次出現的位置
public static int findFirst(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; // 目標值在左半部分或者當前位置就是目標值}}// 當退出循環時,left 指向第一個大于等于目標值的位置return nums[left] == target ? left : -1; // 如果找到目標值,返回該位置;否則返回 -1
}// 找到元素最后一次出現的位置
public static int findLast(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; // 目標值在左半部分}}// 當退出循環時,right 指向最后一個小于等于目標值的位置return right; // 直接返回 right,即最后一次出現的位置
}

5.LeetCode 33 搜索旋轉排序數組

在這里插入圖片描述

  • 解法

題目要求我們設計一個時間復雜度為O(logN)的算法,很容易就想到二分法。

但是本題整個數組并不是完全有序的,而是被“旋轉”拆分成了兩個部分。

如果我們能找到那個旋轉點的話,在兩個有序的部分進行二分查找就非常輕松了。

那么如果直接遍歷數組去找旋轉點的話,時間復雜度還是會上升到O(N),不符合題目要求。

我們能不能也用二分去尋找這個旋轉點呢? 答案是可以的。

eg 4 5 6 7 1 2 3——旋轉點在 1 處
我們以arr[0],也就是4為基準,用mid 去跟 arr[0]比較,如果mid>arr[0],說明旋轉點在mid右邊,如果mid<arr[0],那么可能當前就是旋轉點,或者旋轉點在右邊。

這也算是滿足二段性的一個例子了——二分法并不是一定要有序的時候才能用,滿足二段性時,也可以使用。


//查找旋轉點 
public static int findRotationPointIndex(int[] arr) {// 如果數組長度為2,直接返回較小元素的索引if (arr.length == 2) return arr[0] < arr[1] ? 0 : 1;// 初始化左右邊界int left = 0;int right = arr.length - 1;// 二分查找旋轉點while (left < right) {int mid = left + (right - left) / 2;if (arr[mid] >= arr[0]) {left = mid + 1;  // mid處于前半段遞增序列,旋轉點在右半段} else {right = mid;     // mid處于后半段遞增序列或是旋轉點}}return left;  // left指向旋轉點的索引
}

查找到旋轉點之后,我們再在兩端進行二分查找就比較容易了。

public int search(int[] arr, int target) {// 如果數組長度為1,直接比較目標值與數組唯一元素if (arr.length == 1) return target == arr[0] ? 0 : -1;// 找到旋轉點的索引int index = findRotationPointIndex(arr);// 初始化左右邊界int left = 0;int right = arr.length - 1;// 確定二分查找的范圍if (index == 0) {// 數組沒有旋轉,直接在整個數組上執行二分查找return binaryFind(arr, left, right, target);}if (target >= arr[0]) {right = index; // 目標值可能在旋轉點之前(包括旋轉點)} else {left = index; // 目標值在旋轉點之后}// 在確定的范圍內執行二分查找return binaryFind(arr, left, right, target);}//二分查找public static int binaryFind(int[] arr, int left, int right, int target) {while (left <= right) {int mid = left + (right - left) / 2;if (arr[mid] == target) {return mid;} else if (arr[mid] < target) {left = mid + 1;} else {right = mid - 1;}}return -1;}

在這里插入圖片描述


6.LeetCode 475 供暖器

在這里插入圖片描述

  • 解法

核心思路就是兩句話:
(1)對于每個房屋,要么用前面的暖氣,要么用后面的,二者取近的,得到距離;
(2)對于所有的房屋,選擇最大的上述距離。

所以我們可以將heaters排好序,然后對每個房屋利用二分法去搜索最近的(相鄰的)供暖器即可。

代碼實現:

public int findRadius(int[] houses, int[] heaters) {// 首先對加熱器的位置數組進行排序Arrays.sort(heaters);// 初始化答案為0int ans = 0;int n = houses.length;// 遍歷房屋的位置數組for (int i = 0; i < n; i++) {// 對于每個房屋位置,調用二分查找函數找到其最近的加熱器,并更新答案ans = Math.max(binarySearch(heaters, houses[i]), ans);}// 返回最大半徑return ans;}// 二分查找函數,用于找到距離目標最近的加熱器public int binarySearch(int[] nums, int target) {int n = nums.length;// 如果目標大于等于加熱器數組中最后一個加熱器的位置,直接返回目標與最后一個加熱器位置的距離差if (target >= nums[n - 1]) return target - nums[n - 1];// 如果目標小于等于加熱器數組中第一個加熱器的位置,直接返回第一個加熱器位置與目標的距離差if (target <= nums[0]) return nums[0] - target;// 初始化左右邊界int l = 0, r = n - 1;// 開始二分查找while (l <= r) {int mid = l + (r - l) / 2;if (nums[mid] == target) {return 0; // 如果找到目標位置,返回距離差為0} else if (nums[mid] < target) {l = mid + 1; // 如果目標在當前中間值的右側,更新左邊界} else {r = mid - 1; // 如果目標在當前中間值的左側,更新右邊界}}// 循環結束時,l指向的位置即為最終找到的最近的那個比他大的加熱器的位置//取兩個差值的最小值return Math.min(nums[l] - target, target - nums[l - 1]);}

7.LeetCode 287 尋找重復數

在這里插入圖片描述

  • 這道題博主咋也想不出來能用二分法哈哈哈哈,想破腦殼也找不到二段性

  • 但是 還有有二段性滴~ 哈哈哈哈 剛開始看不太明白沒關系 博主也琢磨了好一會兒 差點放棄了…

  • 自己在紙上找一些例子畫一畫 慢慢就能get到這個點啦

在這里插入圖片描述

  • 代碼實現
// 尋找重復元素的方法,輸入是一個整數數組 nums
public int findDuplicate(int[] nums) {int n = nums.length; // 數組的長度int l = 1, r = n - 1; // 設定搜索范圍,因為題目給出了1到n-1之間的數字重復,所以左邊界為1,右邊界為n-1int ans = -1; // 初始化答案為-1,因為題目保證了一定存在重復元素,因此初始值不影響結果// 開始二分搜索while (l <= r) {int mid = l + (r - l) / 2; // 計算中間值int cnt = 0; // 統計小于等于mid的元素個數for (int num : nums) {if (num <= mid) {cnt++;}}// 如果小于等于mid的元素個數(cnt)小于等于mid本身,則重復元素在[mid+1, r]范圍內if (cnt <= mid) {l = mid + 1; // 更新左邊界,縮小搜索范圍到[mid+1, r]} else {r = mid - 1; // 否則重復元素在[l, mid-1]范圍內ans = mid; // 更新答案為當前的mid,因為mid可能是重復的數字}}return ans; // 返回找到的重復元素
}

博主在這篇博客里面會繼續更新二分查找的算法題哦~

歡迎點贊關注收藏~

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

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

相關文章

(已解決)Adobe Flash Player已不再受支持

文章目錄 前言解決方案 前言 一般來說&#xff0c;很少遇到官方網站使用Adobe Flash Player來進行錄用名單公示了。但是&#xff0c;今天就偏偏遇到一次&#xff0c; 用谷歌瀏覽器打不開&#xff0c; 點了沒有反應&#xff0c;用其他的瀏覽器&#xff0c;例如windows自帶的那…

Golang | Leetcode Golang題解之第207題課程表

題目&#xff1a; 題解&#xff1a; func canFinish(numCourses int, prerequisites [][]int) bool {var (edges make([][]int, numCourses)indeg make([]int, numCourses)result []int)for _, info : range prerequisites {edges[info[1]] append(edges[info[1]], info[0]…

數據結構:期末考 第六次測試(總復習)

一、 單選題 &#xff08;共50題&#xff0c;100分&#xff09; 1、表長為n的順序存儲的線性表&#xff0c;當在任何位置上插入或刪除一個元素的概率相等時&#xff0c;插入一個元素所需移動元素的平均個數為&#xff08; D &#xff09;.&#xff08;2.0&#xff09; A、 &am…

在node環境使用MySQL

什么是Sequelize? Sequelize是一個基于Promise的NodeJS ORM模塊 什么是ORM? ORM(Object-Relational-Mapping)是對象關系映射 對象關系映射可以把JS中的類和對象&#xff0c;和數據庫中的表和數據進行關系映射。映射之后我們就可以直接通過類和對象來操作數據表和數據了, 就…

join()方法——連接字符串、元組、列表和字典

自學python如何成為大佬(目錄):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 語法參考 join()方法用于連接字符串數組。將字符串、元組、列表中的元素以指定的字符&#xff08;分隔符&#xff09;連接生成一個新的字符串&#…

喜報 | 極限科技獲得北京市“創新型”中小企業資格認證

2024年6月20日&#xff0c;北京市經濟和信息化局正式發布《關于對2024年度4月份北京市創新型中小企業名單進行公告的通知》&#xff0c;極限數據&#xff08;北京&#xff09;科技有限公司憑借其出色的創新能力和卓越的企業實力&#xff0c;成功獲得“北京市創新型中小企業”的…

學會python——在excel中寫入數據(python實例十三)

目錄 1.認識Python 2.環境與工具 2.1 python環境 2.2 Visual Studio Code編譯 3 .想Excel中寫入數據 3.1 代碼構思 3.2 代碼實例 3.3 運行結果 4.總結 1.認識Python Python 是一個高層次的結合了解釋性、編譯性、互動性和面向對象的腳本語言。 Python 的設計具有很強的…

數據結構算法之B樹

一、緒論 1.1 數據結構的概念和作用 1.2 B樹的起源和應用領域 二、B樹的基本原理 2.1 B樹的定義和特點 2.2 B樹的結構和節點組成 2.3 B樹的插入 2.4 B樹的刪除操作 三、B樹的優勢和應用 3.1 B樹在數據庫系統中的應用 3.2 B樹在文件系統中的應用 3.3 B樹在內存管理中…

HTML5的多線程技術:Shared Worker的使用示例

Shared Worker 與普通的 Web Worker 類似&#xff0c;但不同之處在于它可以被多個瀏覽器窗口、標簽頁或者iframe共享&#xff0c;使得這些上下文之間能夠相互通信。下面是一個使用 Shared Worker 的完整示例。共享Worker腳本&#xff08;sharedWorker.js&#xff09; self.add…

isupper()方法——判斷字符串是否全由大寫字母組成

自學python如何成為大佬(目錄):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 語法參考 isupper()方法用于判斷字符串中所有的字母是否都是大寫。isupper()方法的語法格式如下&#xff1a; str.isupper() 如果字符串中包含至少…

我是如何在bytemd中實現自定義目錄的

介紹 接著上文說完&#xff0c;實現了在markdown編輯器中插入視頻的能力&#xff0c;接下來還需要繼續優化 markdown文檔的閱讀體驗&#xff0c;比如 再加個目錄 熟悉markdown語法的朋友可能會說&#xff0c;直接在編輯時添加 toc 標簽&#xff0c;可以在文章頂部自動生成目錄…

實驗三 時序邏輯電路實驗

仿真 鏈接&#xff1a;https://pan.baidu.com/s/1z9KFQANyNF5PvUPPYFQ9Ow 提取碼&#xff1a;e3md 一、實驗目的 1、通過實驗&#xff0c;理解觸發的概念&#xff0c;理解JK、D等常見觸發器的功能&#xff1b; 2、通過實驗&#xff0c;加深集成計數器功能的理解&#xff0c;掌…

?Ollama的本地安裝?

先來逛一下咱們的主角Ollama的官網地址&#xff1a; Ollama 大概長這個樣子&#x1f914; 因為本地系統的原因&#xff0c;文章只提供Widows的安裝方式&#xff0c;使用Linux和Mac的大佬&#xff0c;可以自行摸索&#x1f9d0; 下載完成后就是安裝了&#x1f355;&#xff0c…

一、Redis簡介

一、Redis介紹與一般應用 1.1 基本了解 Redis全稱Remote Dictionary Server(遠程字典服務)&#xff0c; 是一個開源的高性能鍵值存儲系統&#xff0c;通常用作數據庫、緩存和消息代理。使用ANSI C語言編寫遵守BSD協議&#xff0c;是一個高性能的Key-Value數據庫提供了豐富的數…

JVM性能監控與調優:生產環境的實踐指南

JVM性能監控與調優&#xff1a;生產環境的實踐指南 一、引言 在生產環境中&#xff0c;Java應用程序的性能監控和調優是確保系統穩定運行、提升用戶體驗的關鍵環節。JVM&#xff08;Java Virtual Machine&#xff09;作為Java應用程序的運行環境&#xff0c;其性能直接影響到…

Flink 本地任務添加配置參數

Flink 本地任務添加配置參數 配置一個Configuration&#xff0c;然后通過StreamExecutionEnvironment.getExecutionEnvironment(configuration)傳入。 例如&#xff1a; Configuration configuration new Configuration();configuration.set(RestartStrategyOptions.RESTART_…

蘋果筆記本能玩網頁游戲嗎 蘋果電腦玩steam游戲怎么樣 蘋果手機可以玩游戲嗎 mac電腦安裝windows

蘋果筆記本有著優雅的機身、強大的性能&#xff0c;每次更新迭代都備受用戶青睞。但是&#xff0c;當需要使用蘋果筆記本進行游戲時&#xff0c;很多人會有疑問&#xff1a;蘋果筆記本能玩網頁游戲嗎&#xff1f;蘋果筆記本適合打游戲嗎&#xff1f;本文將討論這兩個話題&#…

6-14題連接 - 高頻 SQL 50 題基礎版

目錄 1. 相關知識點2. 例子2.6. 使用唯一標識碼替換員工ID2.7- 產品銷售分析 I2.8 - 進店卻未進行過交易的顧客2.9 - 上升的溫度2.10 - 每臺機器的進程平均運行時間2.11- 員工獎金2.12-學生們參加各科測試的次數2.13-至少有5名直接下屬的經理2.14 - 確認率 1. 相關知識點 left …

JavaScript——屬性的檢測和枚舉

目錄 任務描述 相關知識 屬性的檢測 屬性的枚舉 編程要求 任務描述 本關任務&#xff1a;給定一個屬性的名字&#xff0c;請先判斷它屬于哪一個對象&#xff0c;然后返回該對象的所有自有屬性名連接成的字符串。 如&#xff1a;school對象有三個自有屬性name,location,s…

達夢數據庫系列—15. 表的備份和還原

目錄 1、表備份 2、表還原 1、表備份 表備份和表還原恢復&#xff0c;都必須在聯機狀態下進行。 與備份數據庫與表空間不同&#xff0c;不需要備份歸檔日志&#xff0c;不存在增量備份之說。 CREATE TABLE TAB_FOR_RES_02(C1 INT);CREATE INDEX I_TAB_FOR_RES_02 ON TAB_F…