二分查找1

1. 二分查找(704)

題目描述:
在這里插入圖片描述
算法原理:
暴力解法就是遍歷數組來找到相應的元素,使用二分查找的解法就是每次在數組中選定一個元素來將數組劃分為兩部分,然后因為數組有序,所以通過大小關系舍棄一部分數組,最終不斷重復這個過程完成查找,時間復雜度可以達到logN。
代碼如下:

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

題目鏈接

2. 在排序數組中查找元素的第一個和最后一個位置(34)

題目描述:
在這里插入圖片描述
樸素二分查找:
這題我們可以先使用樸素二分查找的方法取找到等于target的元素下標,此時再分別使用兩個循環去比較左右兩邊元素是否與target相等,如果相等則分別向左和向右移動,最終返回對應的下標即可,這個過程很好理解。
代碼如下:

class Solution {public int[] searchRange(int[] nums, int target) {int left = 0, right = nums.length - 1;int index1 = -1, index2 = -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;} else {index1 = mid;index2 = mid;while (index1 - 1 >= 0 && nums[index1] == nums[index1 - 1]) {index1--;}while (index2 + 1 < nums.length && nums[index2] == nums[index2 + 1]) {index2++;}break;}}return new int[] { index1, index2 };}
}

優化樸素二分查找:
首先我們去尋找target的左邊界,為了便于理解我們給出圖1,數組的元素可以分為兩個部分,前半部分是小于target的元素,后一部分是大于等于target的部分。
圖1
在這里插入圖片描述
如圖2,當我們的nums[mid]也就是x落入前半部分的時候,為了去接近target需要使得left=mid+1,當我們的x落入后半部分的時候,此時我們不能夠使right=mid-1,因為如果說此時x是等于target的并且是左邊的最后一個target,那么將right-1后面就直接再也找不到正確的target了。綜上,如果x落入圖1的第二段區間,那么就使得right=mid。很好理解的一點就是通過這樣的操作,left在不斷的向右移動,right在不斷的向左移動但是它的下標也不會超出圖1第二段區間的左邊,這樣我們就能夠找到連續target的左邊界。
圖2
在這里插入圖片描述
然后我們來處理兩個細節問題,第一個問題就是這樣使用二分查找,它的循環條件是使用left<right還是left<=right。我們樸素二分查找是使用后者的,但是在這里要使用前者。為什么呢,這里先分三種情況:
(1)target在right和left區間之內
在這種情況下,最終right會等于left,此時跳出循環即可,直接得到的下標就是正確答案,根本不需要去額外在循環當中去分三種情況> < ==。
(2)left和right區間內都是小于target的
此時left不斷的加一最終和right相等跳出循環即可,然后判斷nums[right]是否等于target。
(3)left和right區間內都是大于target
此時right不斷向右最終和left相等跳出循環。
以上是選擇left<right的原因之一,另一個原因就是使用left<=right會造成死循環,當我們使用圖2中的方法來處理最終得到結果時,此時left等于right,如果使用left<=right下一次不會跳出而是會進入死循環,這一點還是很好理解的。
綜上三種情況,我們使用left<right這樣的循環條件,是因為當跳出循環時我們可以進行判斷nums[right]是否等于target從而直接得到結果,另外可以防止死循環。
第二個細節問題就是中點的選擇,一般是有兩種方式來計算中點如圖3。
圖3
在這里插入圖片描述
圖3中兩種計算中點的方式在樸素二分查找中都是可以適用的,但是這里也就是按照圖2的計算方式來說兩種方式是有差別的,如果我們使用第二種計算方式,如果我們將left和right的區間縮小到兩個元素,也就是left+1等于right這種情況,此時mid計算為right,nums[mid]等于target,right=mid,后面的循環mid經過計算又等于原來的值,由此進入死循環,為了避免這種情況我們就需要使用第一種計算中點的方式。
以上就是求連續的target左邊界的分析,對于右邊界的分析也是類似的,唯一需要注意的就是此時計算中點的方式要選擇第二種否則會造成死循環。
優化后代碼如下:

class Solution {public int[] searchRange(int[] nums, int target) {int left1 = 0, right1 = nums.length - 1;if (right1 == -1) {return new int[] { -1, -1 };}int[] ret = new int[2];while (left1 < right1) {int mid1 = left1 + (right1 - left1) / 2;if (nums[mid1] < target) {left1 = mid1 + 1;} else {right1 = mid1;}}if (nums[right1] == target) {ret[0] = right1;} else {ret[0] = -1;}int left2 = 0, right2 = nums.length - 1;while (left2 < right2) {int mid2 = left2 + (right2 - left2 + 1) / 2;if (nums[mid2] > target) {right2 = mid2 - 1;} else {left2 = mid2;}}if (nums[left2] == target) {ret[1] = left2;} else {ret[1] = -1;}return ret;}
}

解題模板:
在這里插入圖片描述
下面出現減一上面就需要加一。
題目鏈接

3. 搜索插入位置(35)

題目描述:
在這里插入圖片描述
在這里插入圖片描述

算法原理:
根據題目知道,這里的數組是一個升序并且無重復元素的數組,并且如果數組內包含target就求出target的下標,如果數組中不包含target就求出第一個大于target的數的下標,這就是題目的要求。那么我們就可以將數組分為兩部分,第一部分是小于target的部分,第二個部分是大于等于target的部分,那么我們直接求出第二部分的左邊界即可。前面的題目我們也給出了模板以及解題的思路,具體看代碼。
代碼如下:

class Solution {public int searchInsert(int[] nums, int target) {int left = 0, right = nums.length - 1;if (nums[right] < target) {return right + 1;}while (left < right) {int mid = left + (right - left) / 2;if (nums[mid] < target) {left = mid + 1;} else {right = mid;}}return right;}
}

題目鏈接

4. x 的平方根 (69)

題目描述:
在這里插入圖片描述

算法原理:
根據題目我們知道可以將1到x就當成數組中的數,然后我們需要去找到一個數n去滿足n*n等于x,這個n就可以使用二分查找來進行尋找,將1到x分為兩部分,一部分是數的平方小于等于x另一部分是數的平方大于x,顯然我們只需要找到第一部分的右邊界即可。不過這題提交的時候要注意數據溢出的問題,要確定好數的類型。
代碼如下:

class Solution {public int mySqrt(int x) {if (x == 0) {return 0;}int right = x, left = 1;while (left < right) {long mid = left + (right - left + 1) / 2;if (mid * mid <= x) {left = (int) mid;} else {right = (int) mid - 1;}}return left;}
}

題目鏈接

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

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

相關文章

七天速通javaSE:第五天 數組基礎

文章目錄 前言一、認識數組二、數組的聲明和創建1. 聲明數組變量2. 創建數組3. 變量的初始化&#xff08;賦值&#xff09;3.1 靜態初始化3.2 動態初始化 3. 示例 三、數組的使用1. 循環1.1 普通for循環1.2 For-Each 循環 2. 數組作為函數的參數和返回值 前言 本文將為大家介紹…

Win11 Python3.10 安裝pytorch3d

0&#xff0c;背景 Python3.10、cuda 11.7、pytorch 2.0.1 閱讀【深度學習】【三維重建】windows10環境配置PyTorch3d詳細教程-CSDN博客 1&#xff0c;解決方法 本來想嘗試&#xff0c;結果發現CUB安裝配置對照表里沒有cuda 11.7對應的版本&#xff0c;不敢輕舉妄動&#x…

0051__win - RegisterWaitForSingleObject的例子

win - RegisterWaitForSingleObject的例子_registerwaitforsingleobject msdn-CSDN博客

DP:子序列問題

文章目錄 什么是子序列子序列的特點舉例說明常見問題 關于子序列問題的幾個例題1.最長遞增子序列2.擺動序列3.最長遞增子序列的個數4.最長數對鏈5.最長定差子序列 總結 什么是子序列 在計算機科學和數學中&#xff0c;子序列&#xff08;Subsequence&#xff09;是指從一個序列…

c語言的燙燙燙燙燙??

當初學習C語言時&#xff0c;對于一些特殊的打印輸出可能會感到困惑&#xff0c;比如會出現一堆亂碼燙燙燙的情況。其實這是因為在C語言中&#xff0c;對于字符類型和數字類型之間的隱式轉換可能會導致打印輸出的結果不符合預期。這并不意味著程序員"燙"&#xff0c;…

[激光原理與應用-96]:激光器研發與生產所要的常見設備(大全)與儀器(圖解)

目錄 一、激光器制造設備 二、測試與校準設備 2.1 光功率計&#xff1a; 1、工作原理 2、主要功能 3、應用場景 4、測量方法 5、總結 2.2. 激光束質量分析儀&#xff1a; 1、概述 2、主要功能和特點 3、工作原理 4、常見品牌和型號 5、應用領域 6、總結 2.3 光…

力扣-2529. 正整數和負整數的最大計數

文章目錄 力扣題目代碼工程 力扣題目 給你一個按 非遞減順序 排列的數組 nums &#xff0c;返回正整數數目和負整數數目中的最大值。 換句話講&#xff0c;如果 nums 中正整數的數目是 pos &#xff0c;而負整數的數目是 neg &#xff0c;返回 pos 和 neg二者中的最大值。 注…

機器人運動范圍檢測 c++

地上有一個m行n列的方格&#xff0c;一個機器人從坐標&#xff08;0&#xff0c;0&#xff09;的格子開始移動&#xff0c;它每次可以向上下左右移動一個格子&#xff0c;但不能進入行坐標和列坐標的位數之和大于k的格子&#xff0c;請問機器人能夠到達多少個格子 #include &l…

基于大數據架構的情感分析

1 項目介紹 1.1 研究目的和意義 隨著大數據時代的到來&#xff0c;電影產業積累了海量的用戶評論數據&#xff0c;這些數據中蘊含著觀眾的情感傾向與偏好信息&#xff0c;為電影推薦和市場策略制定提供了寶貴資源。然而&#xff0c;如何高效地從這浩瀚的數據海洋中提煉出有價…

QT5:在窗口右上角顯示圖標

目錄 一、環境與目標 二、實現邏輯&#xff08;純代碼&#xff09;與效果 三、參考代碼 四、總結 一、環境與目標 qt版本&#xff1a;5.12.7 windows 11 下的 Qt Designer &#xff08;已搭建&#xff09; 目標&#xff1a;使用嵌套布局的方式將兩個按鈕顯示在窗口右上角…

《大海》這歌為何經久不衰?你看歌詞寫的多美妙!

《大海》這歌為何經久不衰&#xff1f;你看歌詞寫的多美妙&#xff01; 《大海》是一首由陳大力作詞&#xff0c;陳大力、陳秀男作曲&#xff0c;Ricky Ho編曲&#xff0c;張雨生演唱的國語流行歌曲。該曲收錄在張雨生1992年11月30日由飛碟唱片發行的同名專輯《大海》中。 作為…

【JavaEE精煉寶庫】多線程進階(2)synchronized原理、JUC類——深度理解多線程編程

一、synchronized 原理 1.1 基本特點&#xff1a; 結合上面的鎖策略&#xff0c;我們就可以總結出&#xff0c;synchronized 具有以下特性(只考慮 JDK 1.8)&#xff1a; 開始時是樂觀鎖&#xff0c;如果鎖沖突頻繁&#xff0c;就轉換為悲觀鎖。 開始是輕量級鎖實現&#xff…

廣州外貿建站模板

Yamal外貿獨立站wordpress主題 綠色的亞馬爾Yamal外貿獨立站wordpress模板&#xff0c;適用于外貿公司建獨立站的wordpress主題。 https://www.jianzhanpress.com/?p7066 賽斯科Sesko-W外貿建站WP主題 適合機械設備生產廠家出海做外貿官網的wordpress主題&#xff0c;紅橙色…

Dify自定義工具例子

1.天氣&#xff08;JSON&#xff09; {"openapi": "3.1.0","info": {"title": "Get weather data","description": "Retrieves current weather data for a location.","version": "v1…

動態規劃——打家劫舍(C++)

好像&#xff0c;自己讀的書確實有點少了。 ——2024年7月2日 198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 題目描述 你是一個專業的小偷&#xff0c;計劃偷竊沿街的房屋。每間房內都藏有一定的現金&#xff0c;影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連…

Linux 靜態庫和動態庫

不管是Linux還是Windows中的庫文件其本質和工作模式都是相同的, 只不過在不同的平臺上庫對應的文件格式和文件后綴不同。程序中調用的庫有兩種 靜態庫和動態庫&#xff0c;不管是哪種庫文件本質是還是源文件&#xff0c;只不過是二進制格式只有計算機能夠識別&#xff0c;作為一…

【Node-RED 4.0.2】4.0版本新增特性(官方版)

二、重要功能 *1.時間戳格式改進 過去&#xff0c;node-red 只提供了 最原始的 timestamp 的格式&#xff08;1970-01-01 ~ now&#xff09; 但是現在&#xff0c;額外增加了 2 種格式&#xff1a; ISO 8601 -A COMMON FORMAT&#xff08;YYYY-MM-DDTHH:mm:ss:sssZ&#xff…

思考如何學習一門編程語言?

一、什么是編程語言 編程語言是一種用于編寫計算機程序的人工語言。通過編程語言&#xff0c;程序員可以向計算機發出指令&#xff0c;控制計算機執行各種任務和操作。編程語言由一組語法規則和語義規則組成&#xff0c;這些規則定義了如何編寫代碼以及代碼的含義。 編程語言…

linux和mysql基礎指令

Linux中nano和vim讀可以打開記事文件。 ifdown ens33 ifup ens33 關閉&#xff0c;開啟網絡 rm -r lesson1 gcc -o code1 code1.c 編譯c語言代碼 ./code1 執行c語言代碼 rm -r dir 刪除文件夾 mysql> show databases-> ^C mysql> show databases; -------…

常見網絡端口號

在網絡工程領域&#xff0c;了解和掌握默認端口號是至關重要的。端口號是計算機網絡中最基本的概念之 一&#xff0c;用于標識特定的網絡服務或應用程序。 1、什么是端口號&#xff1f; 端口號是計算機網絡中的一種標識&#xff0c;用于區分不同的網絡服務和應用程序。每個端…