算法入門-二分搜索(長期更新)

文章目錄

      • 情景一 : 二分查找
      • 情景二 : 找出一個 >= num 的最左側的位置
      • 情景三 : 找出一個 <= num 的最右側的位置
      • leetcode 162 :尋找峰值
      • leetcode 69 : x 的平方根

首先來簡介一下二分搜索算法,二分搜索是一種每次砍半的算法,最經典的案例當然是我們的二分查找算法,但是大部分人所認知的二分搜索都是必須要滿足這個 數組有序,才可以進行,其實不然,二分的本質邏輯是建立在"砍半",而砍半的本質就是你知道那一半一定沒有,而另一半不一定有的前提下,只要滿足了這一前提條件,那么你就可以盡可以進行二分…這個算法的時間復雜度是O(logN)
我們這個算法的系列將會長期更新,在遇見好題了之后就會加進來進行整理

情景一 : 二分查找

這個是二分最經典的情景,也就是在一個數組中進行每次砍半的查找元素
代碼實現如下

public static int myBinarySearch(int[] nums,int key){if(nums == null || nums.length == 0){System.out.println("無法進行搜索");return -1;}int left = 0;int right = nums.length - 1;int mid;while(left <= right){//請注意這里我們對于我們這個平均值的處理情況mid = left + ((right - left)>>1);if(nums[mid] > key){right = mid - 1;}else if(nums[mid] < key){left = mid + 1;}else{return mid;}}return -1;}

注意一下我們這里的求其平均值的操作,是利用位運算,其一是防止其溢出,其二是加快運算的速度,因為位運算的速度要遠大于除法運算…

情景二 : 找出一個 >= num 的最左側的位置

這個其實也是二分的邏輯,我們定義一個標記物 ans 初始化置為-1,當我們的mid滿足條件的時候,我們就將我們的ans置為 mid ,然后繼續二分,當不滿足條件的時候,我們就不進行操作,繼續二分,然后最后返回我們的 ans 標記物…
代碼實現如下 :

/***      情景二 : 找到 >= num 的最左側的位置*      這個基本的邏輯跟二分搜索法其實是一致的,但是也是有一定的差別,比如這個必須要搜索徹底才可以*      當每次滿足條件的時候,就進行 ans 的更新...直到left == right;**      可能你有疑問:為什么我們不進行 <= num 的最左側位置的查找 ...*      因為這個問題是沒有意義的..因為只需要判斷 nums[0] 跟 key的關系* @param nums : 待搜索的數組* @param key : 待定的查找元素* @return*/public static int findNumMaxLeft(int[] nums,int key){if(nums == null || nums.length == 0){System.out.println("無法進行搜索");return -1;}int left = 0;int right = nums.length - 1;int mid;int ans = -1;while(left <= right){mid = left +((right - left) >> 1);if(nums[mid] >= key){ans = mid;right = mid - 1;}else if(nums[mid] < key){left = mid + 1;}}return ans;}

情景三 : 找出一個 <= num 的最右側的位置

這個其實跟情景二是對稱的,原理是一致的,當滿足條件的時候記錄下來繼續進行二分,當不滿足條件的時候不進行記錄然后繼續進行二分,到二分到不能再次進行二分的情況之后,就返回我們的標記ans值…
代碼實現如下:

public static int findNumMinRight(int[] nums,int key){if(nums == null || nums.length == 0){System.out.println("無法進行搜索");return -1;}int left = 0;int right = nums.length - 1;int mid;int ans = -1;while(left <= right){mid = left +((right - left) >> 1);if(nums[mid] <= key){left = mid + 1;ans = mid;}else if(nums[mid] > key){right = mid - 1;}}return ans;}

leetcode 162 :尋找峰值

在這里插入圖片描述
首先我們來分析一下這個題干,這個數組中相鄰的兩個元素都是不相等的,然后讓你返回其中的一個峰值(任意一個就可以),那這道題為什么可以進行二分呢…,我們來看體重的假設提示,我們假設 nums[-1] 和 nums[n] 都是 負無窮
首先我們判斷一下特殊的情況,假設我們的 第一個元素大于第二個元素,所以此時第一個元素就是局部的峰值(其實這里有點類似函數極值點的概念),對應的如果最后一個元素要大于倒數第二個元素,那么最后一個元素就是峰值

特殊情況的制約if(nums == null || nums.length == 0){System.out.println("這個數組不可能存在峰值");return -1;}//下面都是一些特殊情況的判斷...(端點處的極值問題)if(nums.length == 1){return 0;}if(nums[0] > nums[1]){return 0;}if(nums[nums.length-1] > nums[nums.length - 2]){return nums.length - 1;}

下面我們進行一般情況的分析
在這里插入圖片描述
我們現在不滿足特殊條件,所以我們數組的走向是這樣的,那么因為我的開頭處是上升,終點位置是下降,所以中間的某個位置一定存在至少一個極值點(有點類似中值定理) 所以我們可以進行二分
判斷nums[mid] 和 nums[mid-1] 與nums[mid+1] 之間的關系…
而中值位置情況的只有以下四種
在這里插入圖片描述
其中 1 2 4 都不是我們所需要的,所以要繼續進行二分搜索
所以我們可以寫出如下的代碼

int left = 1;int right = nums.length - 2;int mid;/*** 注意:* 這里的控制條件其實非常合理,在中點處一共只有四種情況,而這個循環的控制體系可以控制其中的三種無峰值的情況...*/while(left <= right){mid = left +((right - left) >> 1);if(nums[mid] < nums[mid - 1]){right = mid - 1;}else if(nums[mid] < nums [mid + 1]){left = mid + 1;}else{return mid;}}return -1;

下面是我們的完整代碼

public static int findPeakNumber(int[] nums){if(nums == null || nums.length == 0){System.out.println("這個數組不可能存在峰值");return -1;}//下面都是一些特殊情況的判斷...(端點處的極值問題)if(nums.length == 1){return 0;}if(nums[0] > nums[1]){return 0;}if(nums[nums.length-1] > nums[nums.length - 2]){return nums.length - 1;}//下面是普通的一個情況//其實有點類似數學的拉格朗日中值定理int left = 1;int right = nums.length - 2;int mid;/*** 注意:* 這里的控制條件其實非常合理,在中點處一共只有四種情況,而這個循環的控制體系可以控制其中的三種無峰值的情況...*/while(left <= right){mid = left +((right - left) >> 1);if(nums[mid] < nums[mid - 1]){right = mid - 1;}else if(nums[mid] < nums [mid + 1]){left = mid + 1;}else{return mid;}}return -1;}

leetcode 69 : x 的平方根

在這里插入圖片描述
這就是一個典型的可以進行二分的題
這個題的核心邏輯跟我們第三個題 : 找出 >= num 的最右側位置是一致的
值得一提的是,我們這個題要控制我們的算數范圍,否則就會出現溢出的問題,下面就是我們的代碼解析…沒啥可說的了

/***  找出一個數的算術平方根向下取證的那個數然后返回* @param x : 待定的開方數* @return*/public static int mySqrt(int x){if(x == 0){return 0;}int left = 1;int right = x / 2;int mid;int ans = -1;while(left <= right){mid = left + ((right - left)>>1);if(mid <= x/mid){ans = mid;left = mid + 1;}else if(mid > x/mid){right = mid - 1;}}return ans;}

唯一要注意的一點就是,這里我們不可以用mid*mid <= x,要改成除法,用mid <= x / mid,否則這個題就會數值溢出導致出錯…

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

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

相關文章

【JAVA重要知識 | 第一篇】一篇文章讀懂HashMap(存儲、擴容、初始化過程)

文章目錄 1.一篇文章讀懂HashMap&#xff08;存儲、擴容、初始化過程&#xff09;1.1HashMap簡介1.1.1特點1.1.2優點1.1.3缺點 1.2深入解讀HashMap1.2.1常用常量和變量&#xff08;1&#xff09;常用常量&#xff08;2&#xff09;常用變量 1.2.2存儲過程&#xff08;1&#xf…

診所門診電子處方軟件操作教程及試用版下載,醫務室處方箋管理系統模板教程

診所門診電子處方軟件操作教程及試用版下載&#xff0c;醫務室處方箋管理系統模板教程 一、前言 以下軟件程序教程以 佳易王診所電子處方軟件V17.0為例說明 軟件文件下載可以點擊最下方官網卡片——軟件下載——試用版軟件下載 如上圖&#xff0c;點擊基本信息設置——處方配…

Acwing---1208. 翻硬幣

翻硬幣 1.題目2.基本思想3.代碼實現 1.題目 小明正在玩一個“翻硬幣”的游戲。 桌上放著排成一排的若干硬幣。我們用 * 表示正面&#xff0c;用 o 表示反&#xff08;是小寫字母&#xff0c;不是零&#xff09;。 比如&#xff0c;可能情形是&#xff1a;**oo***oooo 如果同…

Python編程小案例—利用flask查詢本機IP歸屬并輸出網頁圖片

Python編程小案例—利用flask查詢本機IP歸屬并輸出網頁圖片 環境&#xff1a;Pycharm Mac OS 源碼如下&#xff1a; from flask import Flask, render_template, requestapp Flask(__name__)app.route(/) def index():return render_template(IP查詢.html)if __name__ __…

文心一言 Python編程之

給一個包含n個整數的數組nums&#xff0c;判斷nums中是否存在三個元素a,b,c&#xff0c;使得abc0?請你找出所有和為0且不重復的三元組。 注意&#xff1a;答案中不可以包含重復的三元組。 示例1&#xff1a; 輸入&#xff1a;nums[-1,0,1,2,-1,-4] 輸出&#xff1a;[[-1,-1,2…

中介者模式

定義&#xff1a;中介者模式&#xff08;Mediator Pattern&#xff09;又稱為調節者模式或調停者模式。用一個中介對象封裝一系列的對象交互&#xff0c;中介者使各對象不需要顯式的相互作用&#xff0c;從而使其耦合松散&#xff0c;而且可以獨立地改變它們之間的交互。 適用…

如何正確選擇一臺大路燈?2024五大出眾品牌大路燈推薦,附超全科普知識整理

大路燈的使用操作非常簡便&#xff0c;而且能夠提供最適合目前用眼的光線環境。但如今市場中卻有一些劣質大路燈&#xff0c;它們的使用體驗不佳&#xff0c;很多客戶反饋說可能會出現光線不穩定、刺眼等問題&#xff0c;甚至會有讓用戶有損傷視力的風險。那么如何選擇一臺大路…

華碩ROG玩家國度幻16air 2024原裝系統恢復安裝教程方法

華碩ROG玩家國度幻16air 2024原裝系統恢復安裝教程方法 重建ASUSRECOVERY恢復功能 支持型號&#xff1a; GU605MI&#xff0c;GU605MY&#xff0c;GU605MZ GU605MV&#xff0c;GU605MU 分3種安裝方法 遠程恢復安裝&#xff1a;https://pan.baidu.com/s/166gtt2okmMmuPUL1…

Spring對IoC的實現

個人名片&#xff1a; &#x1f43c;作者簡介&#xff1a;一名大三在校生&#xff0c;喜歡AI編程&#x1f38b; &#x1f43b;???個人主頁&#x1f947;&#xff1a;落798. &#x1f43c;個人WeChat&#xff1a;hmmwx53 &#x1f54a;?系列專欄&#xff1a;&#x1f5bc;?…

Qt使用QSettings類來讀寫ini

在Qt中&#xff0c;可以使用QSettings類來讀寫ini文件。QSettings提供了一個簡單的接口&#xff0c;用于訪問和修改ini文件中的鍵值對。 下面是使用QSettings類來寫入ini文件的示例代碼&#xff1a; #include <QCoreApplication> #include <QSettings>int main(i…

前端monorepo大倉共享復雜業務組件最佳實踐

一、背景 在 Monorepo 大倉模式中&#xff0c;我們把組件放在共享目錄下&#xff0c;就能通過源碼引入的方式實現組件共享。越來越多的應用愿意走進大倉&#xff0c;正是為了享受這種組件復用模式帶來的開發便利。這種方式可以滿足大部分代碼復用的訴求&#xff0c;但對于復雜…

JAVA *數據庫連接池 * 接JDBC

一.介紹: 數據庫連接池實際上就是一個 " 容器 " 當有多個擁護需要訪問數據庫的時候, 一個用戶會打開一個數據庫連接, 但是!當用戶離開的時候,就會斷開數據庫連接,那么數據庫連接就作廢了,之后如果還有用戶需要進行訪問,需要再建立一個數據庫連接......循環往復, …

【Mybatis】快速入門 基本使用 第一期

文章目錄 Mybatis是什么&#xff1f;一、快速入門&#xff08;基于Mybatis3方式&#xff09;二、MyBatis基本使用2.1 向SQL語句傳參2.1.1 mybatis日志輸出配置2.1.2 #{}形式2.1.3 ${}形式 2.2 數據輸入2.2.1 Mybatis總體機制概括2.2.2 概念說明2.2.3 單個簡單類型參數2.2.4 實體…

Web組態可視化編輯器 快速繪制組態

隨著工業智能制造的發展&#xff0c;工業企業對設備可視化、遠程運維的需求日趨強烈&#xff0c;傳統的單機版組態軟件已經不能滿足越來越復雜的控制需求&#xff0c;那么實現Web組態可視化界面成為了主要的技術路徑。 行業痛點 對于軟件服務商來說&#xff0c;將單機版軟件轉變…

計算機視覺基礎知識(十六)--圖像識別

圖像識別 信息時代的一門重要技術;目的是讓計算機代替人類處理大量的物理信息;隨著計算機技術的發展,人類對圖像識別技術的認識越來越深刻;圖像識別技術利用計算機對圖像進行處理\分析\理解,識別不同模式的目標和對象;過程分為信息的獲取\預處理\特征抽取和選擇\分類器設計\分…

重拾C++之菜鳥刷算法第6篇---棧與隊列

棧與隊列 一、用棧實現隊列 題目 請你僅使用兩個棧實現先入先出隊列。隊列應當支持一般隊列支持的所有操作&#xff08;push、pop、peek、empty&#xff09;&#xff1a; 實現 MyQueue 類&#xff1a; void push(int x) 將元素 x 推到隊列的末尾int pop() 從隊列的開頭移除…

【Hadoop】使用Metorikku框架讀取hive數據統計分析寫入mysql

一、定義作業文件 作業文件 該文件將包括輸入源、輸出目標和要執行的配置文件的位置&#xff0c;具體內容如下 metrics:- /user/xrx/qdb.yaml # 此位置為hdfs文件系統目錄 inputs: output:jdbc:connectionUrl: "jdbc:mysql://233.233.233.233:3306/sjjc"user: &quo…

虛擬帆船:利用技術出海的探險家

在數字化的浪潮中&#xff0c;一個新時代的探險家誕生了。他們不是在尋找未知大陸的勇士&#xff0c;而是在尋求跨界電商和全球游戲市場的先鋒。這些現代探險家的帆船是由SOCKS5代理和代理IP構成的&#xff0c;他們的海圖則是由數據和市場分析繪制的。 出海的第一步&#xff1a…

WebServer -- 注冊登錄

目錄 &#x1f349;整體內容 &#x1f33c;流程圖 &#x1f382;載入數據庫表 提取用戶名和密碼 &#x1f6a9;同步線程登錄注冊 補充解釋 代碼 &#x1f618;頁面跳轉 補充解釋 代碼 &#x1f349;整體內容 概述 TinyWebServer 中&#xff0c;使用數據庫連接池實現…

Linux 內核irq_stack遍歷

環境Centos 4.18.0-80.el8.x86_64 一、x86架構堆棧類型說明 https://www.kernel.org/doc/Documentation/x86/kernel-stacks int get_stack_info(unsigned long *stack, struct task_struct *task,struct stack_info *info, unsigned long *visit_mask) {if (!stack)goto unk…