日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LeetCode算法题4:二分查找及扩展应用

發布時間:2025/6/17 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LeetCode算法题4:二分查找及扩展应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 一、二分查找
  • 二、第一個錯誤的版本
  • 三、搜索插入位置
  • 總結


前言

??????Leetcode算法系列:https://leetcode-cn.com/study-plan/algorithms/?progress=njjhkd2

??????簡單介紹總結一下二分查找相關的算法題:

一、二分查找

??????題目鏈接:https://leetcode-cn.com/problems/binary-search/

??????題目描述:給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。

??????思路:直接采用通用的二分查找算法即可:

class Solution {public int search(int[] nums, int target) {int start=0,end=nums.length-1,mid;while(start<=end){mid=(start+end)/2; // 最好改為:mid = start+(end-start)/2;if(nums[mid]==target)return mid;else if(nums[mid]<target)start=mid+1;elseend=mid-1;}return -1;} }

??????1,取 mid 值時,采用 mid = start+(end-start)/2; 可以避免當 start 和 end 很大時造成的整數(int)越界。
??????2,循環結束條件為 start<=end,所以在 while 循環退出時有 start>end,(在此為 start=end+1)。
??????3,二分查找的時間復雜度為 O(logn),因為每次循環都會將待處理數組的規模縮小一半。

二、第一個錯誤的版本

??????題目鏈接:https://leetcode-cn.com/problems/first-bad-version/

??????題目描述:你是產品經理,目前正在帶領一個團隊開發新的產品。不幸的是,你的產品的最新版本沒有通過質量檢測。由于每個版本都是基于之前的版本開發的,所以錯誤的版本之后的所有版本都是錯的。

假設你有 n 個版本 [1, 2, …, n],你想找出導致之后所有版本出錯的第一個錯誤的版本。

你可以通過調用 bool isBadVersion(version) 接口來判斷版本號 version 是否在單元測試中出錯。實現一個函數來查找第一個錯誤的版本。你應該盡量減少對調用 API 的次數。

??????思路:保持之間的二分查找框架不變,修改循環退出條件為當前版本正確且上一個版本錯誤,

public class Solution extends VersionControl {public int firstBadVersion(int n) {if(isBadVersion(1))return 1;int start=2,mid; //區間為[2,n].while(start<=n){ //還是按照二分查找的思路來做mid=start+(n-start)/2;if(!isBadVersion(mid)) //縮小區間到[mid+1,n]start=mid+1;else if(!isBadVersion(mid-1)) //如果mid為true,mid-1為false,返回mid即可return mid; else //如果mid-1不是false,縮小區間到[start,mid-1]n=mid-1;}return -1;} }

??????缺點時要調用兩次 isBadVersion函數。

??????Version2:修改循環判定條件為start<end,在循環退出時的 start 或 end 為我們感興趣的下標值。并采用合理的縮小規模方式在循環內僅調用一次 isBadVersion 函數。如下:

public class Solution extends VersionControl {public int firstBadVersion(int n) {int start=1,mid;while(start<n){mid=start+(n-start)/2;if(!isBadVersion(mid))start=mid+1;elsen=mid;}return start;} }

??????上述算法看起來很巧妙,甚至成功的有點僥幸,因為在每次計算 mid 值時,由于向下取整,所以有時候會出現 mid==start 出現,而不會存在 mid==n 出現。因此令 n=mid;這樣在每次循環時區間規模總會縮小,直至得到最終結果。

??????在縮小區間時,最好不要采用 start==mid,很有可能區間不會縮小,陷入死循環。比如當要求找到最后一個正確的版本時會發生這種情況。

三、搜索插入位置

??????題目鏈接:https://leetcode-cn.com/problems/search-insert-position/

??????題目描述:給定一個排序數組和一個目標值,在數組中找到目標值,并返回其索引。如果目標值不存在于數組中,返回它將會被按順序插入的位置。

請必須使用時間復雜度為 O(log n) 的算法。

??????思路:采用通用的二分查找框架,如果目標值存在于數組中,由 mid 給出其返回下標;如果不存在的話,由 start 或 end+1 給出返回下標。

class Solution {public int searchInsert(int[] nums, int target) {int start=0,end=nums.length-1,mid;while(start<=end){mid=start+(end-start)/2;if(nums[mid]==target)return mid;else if(nums[mid]<target)start=mid+1;elseend=mid-1;}return start; //關鍵點在于確定最后一個查找區間和target之間的關系。//return end+1;} }

??????由 start 或 end+1 給出返回值下標的原因在于:在一個不含目標值的升序數組中采用通用的二分查找算法查找 target 的位置,在循環結束后 end 處的值剛好小于 target;start 處的值剛好大于 target。 比如對于數組 [1,3,4,6,7],查找 5 所在位置:循環結束后 start =3,end = 2。

??????Version2:修改循環判定條件為start<end,在循環退出時的 start 或 end 為我們感興趣的下標值。如下:

public int searchInsert(int[] nums, int target) {int end=nums.length-1,start=0,mid;// 特殊判斷if (nums[end] < target) return end+1;// 程序走到這里一定有 nums[end] >= target,保證插入位置在區間 [start..end]while(start<end){mid=start+(end-start)/2;if(nums[mid]<target)start=mid+1;// 下一輪搜索的區間是 [mid + 1..end]elseend=mid;// 下一輪搜索的區間是 [start..mid]}return end;}

??????和 二、查找錯誤的版本類似:在循環中令 end=mid 來保證循環執行結束。


總結

??????通用的二分查找判定條件為 start<=end,意味著結果在循環中給出;當采用 start<end 時,結果在循環執行后由 start 或 end 給出。

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的LeetCode算法题4:二分查找及扩展应用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。