二分法變種小結(leetcode 34、leetcode33、leetcode 81、leetcode 153、leetcode 74)

目錄

  • 二分法細節
  • 1、leetcode 34 在排序數組中查找元素的第一個和最后一個位置
  • 2、不完全有序下的二分查找(leetcode33. 搜索旋轉排序數組)
  • 3、含重復元素的不完全有序下的二分查找(81. 搜索旋轉排序數組 II)
  • 3、不完全有序下的找最小元素(153. 尋找旋轉排序數組中的最小值)
  • 4、二維矩陣二分(74. 搜索二維矩陣)

二分法細節

1、計算mid時,不能使用(left + right)/2,否則有可能計算溢出。
可以使用下面方法計算:

mid = left + ((right - left) >> 1)

2、while(left <= right),注意符號為 <=
如果是 left < right,則當我們執行到最后一步,left與right重疊時,則會跳出循環。但是事實是,此時的left和right指向的可能就是我們的目標元素。
3、 left = mid + 1,right = mid - 1;
如果設置left = mid ,right = mid,left=1,right = 8,mid = 7,會陷入死循環,mid一直為7.

在這里插入圖片描述

1、leetcode 34 在排序數組中查找元素的第一個和最后一個位置

https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/
在普通的二分上加上檢索區間的左右邊界,需要注意特殊的輸入情況。

class Solution {
public:vector<int> searchRange(vector<int>& nums, int target) {if(nums.empty()) return{-1,-1};int left = 0;int right = nums.size() - 1;while(left <= right){int mid = left + ((right - left) >> 1);if(nums[mid] == target){int l = mid;int r = mid;//尋找左邊界//尋找右邊界while( l >= 0 && nums[l] == target) l--;while(r <= nums.size() - 1 && nums[r] == target) r++;l += 1;r -= 1;if(l < 0) l = 0;if(r > nums.size() - 1) r = nums.size() - 1;return {l,r};}else if(nums[mid] > target){right = mid -1;}else{left = mid + 1;}}return {-1,-1};}
};

2、不完全有序下的二分查找(leetcode33. 搜索旋轉排序數組)

https://leetcode-cn.com/problems/search-in-rotated-sorted-array/
升序排列的整數數組 nums 在預先未知的某個點上進行了旋轉(例如, [0,1,2,4,5,6,7] 經旋轉后可能變為 [4,5,6,7,0,1,2] )。

請你在數組中搜索 target ,如果數組中存在這個目標值,則返回它的索引,否則返回 -1 。
注意這里的數組中不包含重復的元素。
示例 1:

輸入:nums = [4,5,6,7,0,1,2], target = 0
輸出:4

示例 2:

輸入:nums = [4,5,6,7,0,1,2], target = 3
輸出:-1

示例 3:

輸入:nums = [1], target = 0
輸出:-1

之前使用的二分都是在數組是有序的背景下,如果不完全有序時也是可以使用二分查找的。
已知分開來的兩個子數組都是有序遞增的。那么如果nums[mid]>= nums[left]則說明mid和left一定落在同一個子數組里,反之nums[mid]< nums[left],說明mid和left不在同一個子數組里,并且此時可以肯定left在數組1,mid在數組2。
注意這里的mid還是通過left和right的下標來求得的,也就是說mid還是在left與right之間。
如果mid和left在同一個子數組中,那么target一共有2種分布的可能:
1、target在mid左邊,此時有target >= nums[left] && target < nums[mid],令right = mid - 1,這樣就在有序的數組1中進行尋找了
2、target在mid右邊,此時有 target > nums[mid] || target < nums[left],令left = mid + 1,緩慢地將left和right指針驅趕到同一個有序區間內。
在這里插入圖片描述
如果mid和right在同一個子數組中,那么target一共有2種分布的可能:
1、target <= nums[right] && target > nums[mid]
此時查找部分就落在右半部分,令left= mid + 1,這樣就在有序的數組2中進行尋找了
2、target > nums[right] || target < nums[mid]
此時mid落在左半部分,應該令right = mid - 1,將兩個指針驅趕到同一個有序區間內
在這里插入圖片描述
AC代碼

class Solution {
public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size() - 1;while(left <= right){int mid = left + ((right - left) >> 1);if(nums[mid] == target){return mid;}//left and mid 落在同一個數組if(nums[mid] >= nums[left]){//mid和left一個數組,target在左邊數組if(target >= nums[left] && target < nums[mid]){right = mid - 1;}//mid和right一個數組else if(target > nums[mid] || target < nums[left]){left = mid + 1;}}//left and mid 落在不同數組else if(nums[mid] < nums[left]){//target在mid 和 right之間if(nums[mid] < target && target <= nums[right]){left = mid + 1;}//target在left 和mid之間else if(target > nums[right] || target < nums[mid]){right = mid - 1;}}}//沒有查找到return -1;}
};

這一題思路還是比較麻煩的,不易想到,還需要加深理解才行。

3、含重復元素的不完全有序下的二分查找(81. 搜索旋轉排序數組 II)

https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。

( 例如,數組 [0,0,1,2,2,5,6] 可能變為 [2,5,6,0,0,1,2] )。

編寫一個函數來判斷給定的目標值是否存在于數組中。若存在返回 true,否則返回 false。

示例 1:

輸入: nums = [2,5,6,0,0,1,2], target = 0
輸出: true

示例 2:

輸入: nums = [2,5,6,0,0,1,2], target = 3
輸出: false

進階:
這是 搜索旋轉排序數組 的延伸題目,本題中的 nums 可能包含重復元素。
這會影響到程序的時間復雜度嗎?會有怎樣的影響,為什么?
如果我們直接套用之前的思路會發現出現下面的問題:
在這里插入圖片描述
原因就是nums[left] == nums[mid]時,這里可能會有問題。
這時我們需要讓left++即可。注意在書寫代碼的時候我們需要在left++后這次循環就結束,所以我們把nums[left] == nums[mid]的情況放到最后處理即可:

class Solution {
public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size() - 1;while(left <= right){int mid = left + ((right - left) >> 1);if(nums[mid] == target){return true;}//left and mid 落在同一個數組if(nums[mid] > nums[left]){//mid和left一個數組,target在左邊數組if(target >= nums[left] && target < nums[mid]){right = mid - 1;}//mid和right一個數組else if(target > nums[mid] || target < nums[left]){left = mid + 1;}}//left and mid 落在不同數組else if(nums[mid] < nums[left]){//target在mid 和 right之間if(nums[mid] < target && target <= nums[right]){left = mid + 1;}//target在left 和mid之間else if(target > nums[right] || target < nums[mid]){right = mid - 1;}}elseleft++;}//沒有查找到return false;}
};

3、不完全有序下的找最小元素(153. 尋找旋轉排序數組中的最小值)

https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array/
假設按照升序排序的數組在預先未知的某個點上進行了旋轉。例如,數組 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] 。

請找出其中最小的元素。
示例 1:

輸入:nums = [3,4,5,1,2]
輸出:1

示例 2:

輸入:nums = [4,5,6,7,0,1,2]
輸出:0

示例 3:

輸入:nums = [1]
輸出:1

由于跳變點小于左邊的值,大于右邊的值。所以當nums[mid] < nums[left]時,說明跳變點在mid與left之間,因為mid與right之間必然是遞增的(跳變只有一次)。
當nums[mid] > nums[left]說明mid與left之間是單調遞增的。
當nums[mid] == nums[left]說明此時mid與left重合了,此時需要將left向右移動1格,然后重新迭代。

在這里插入圖片描述

class Solution {
public:int findMin(vector<int>& nums) {if(nums.size() == 1) return nums[0];int left = 0;int right = nums.size() - 1;while(left <= right){if(nums[left] <= nums[right]) return nums[left];int mid = left + ((right - left) >> 1);if(nums[mid] < nums[left]) right = mid;else if(nums[mid] > nums[left]) left = mid + 1;else if(left == mid) left++;}return -1;}
};

4、二維矩陣二分(74. 搜索二維矩陣)

https://leetcode-cn.com/problems/search-a-2d-matrix/
編寫一個高效的算法來判斷 m x n 矩陣中,是否存在一個目標值。該矩陣具有如下特性:

每行中的整數從左到右按升序排列。
每行的第一個整數大于前一行的最后一個整數。
示例 1:
在這里插入圖片描述

輸入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,50]], target = 3
輸出:true

示例 2:
在這里插入圖片描述

輸入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,50]], target = 13
輸出:false

示例 3:

輸入:matrix = [], target = 0
輸出:false

只要將二維數組展開成一維數組即可,用普通的二分。
需要注意的是將mid轉換成行列坐標;

mid/col 得到的是行數
mid % col 得到的是列數

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {//獲得行數int row = matrix.size();if(row == 0) return false;//獲得列數int col = matrix[0].size();int left = 0;int right = row * col - 1;while(left <= right){int mid = left + ((right - left) >> 1);if(target == matrix[mid/col][mid%col]) return true;else if(target > matrix[mid/col][mid%col]) left = mid + 1;else right = mid - 1;}return false;}
};

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

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

相關文章

ID3D11DeviceContext::Dispatch與numthread筆記

假定——[numthreads(TX, TY, TZ)] // 線程組尺寸。既線程組內有多少個線程。Dispatch(GX, GY, GZ); // 線程組的數量。既有多少個線程組。 那么——SV_GroupThreadID{iTX, iTY, iTZ} // 【線程組內的】線程3D編號SV_GroupID{iGX, iGY, iGZ} // 線程組的3D編號SV_DispatchT…

kotlin 查找id_Kotlin程序查找Square區域

kotlin 查找idFormula to find area of Square: area side*side 查找Square面積的公式&#xff1a; area side * side Given the value of side, we have to find the area of Square. 給定side的值&#xff0c;我們必須找到Square的面積。 Example: 例&#xff1a; Input…

小米手環6解決天氣未同步問題

最近我發現了我的米6手環天氣不同步&#xff0c;打開Zepp Life刷新同步也不行&#xff0c;后來我找了一些網上的解決方法&#xff0c;嘗試了一些也還不行&#xff0c;我這人喜歡瞎搗鼓&#xff0c;無意之間給整好了&#xff0c;后來我開始總結自己操作步驟&#xff0c;就在剛才…

c# datetime._C#| DateTime.Month屬性與示例

c# datetime.DateTime.Month屬性 (DateTime.Month Property) DateTime.Month Property is used to get the month component of this object. Its a GET property of DateTime class. DateTime.Month屬性用于獲取此對象的月份組成部分。 這是DateTime類的GET屬性。 Syntax: 句…

C++ 內存分配層次以及memory primitives的基本用法

分配層次 C memory primitives 分配釋放類型是否可重載mallocfree()C函數不可newdeleteC表達式不可::operator new()::operator delete()C函數可allocator::allocate()allocator::deallocate()C標準庫可自由設計并以之搭配任何容器 分配與釋放的四個用法 1、malloc and delet…

jQuery easyui layout布局自適應瀏覽器大小

首先解釋一下標題的含義&#xff0c;當我們用jQuery easyui layout 進行布局的時候&#xff0c;可能會遇到這樣一個問題&#xff0c;那就是當手工調整瀏覽器大小&#xff0c;或者最大化、還原窗口的時候&#xff0c;layout的某個區域不能填充因為瀏覽器擴大而產 生的空白區域&a…

JAVA 作業:圖形界面

自己動手寫的一個小JAVA 程序&#xff1a; 一個學生管理小系統&#xff0c;雖然很挫&#xff0c;但是這我學JAVA的第一步。學了2天JAVA沒有白費&#xff01; 1 import java.awt.*;2 import java.awt.event.*;3 import java.util.ArrayList;4 5 import javax.swing.*;6 7 class …

一、Pytorch對自定義表達式自動求導

例如&#xff1a;y ax bx c&#xff0c;分別對a&#xff0c;b&#xff0c;c求導 若當a3&#xff0c;b4&#xff0c;c5&#xff0c;x1時 import torch from torch import autogradx torch.tensor(1.) a torch.tensor(3.,requires_gradTrue) b torch.tensor(4.,requires…

css菜單下拉菜單_在CSS中創建下拉菜單

css菜單下拉菜單CSS | 創建下拉菜單 (CSS | Creating Dropdown) Trivia: 瑣事&#xff1a; We know the importance of navigation bar on our webpage, we know the importance of a list of items too on our webpage but what is the importance of dropdown in web pages?…

C++ 內存基本構件new/delete的意義、運用方式以及重載方式

目錄一、對new的理解1、new做了什么2、new被編譯器轉為了什么3、operate_new源代碼長啥樣二、對delete的理解1、delete做了什么2、delete被編譯器轉為了什么3、operator delete源代碼長啥樣三、構造函數與析構函數的直接調用參考一、對new的理解 1、new做了什么 C告訴我們&am…

二、線性代數

一、張量 張量表示由一個數值組成的數組&#xff0c;這個數組可能有多個維度 import torchx torch.arange(15) x # tensor([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])1&#xff0c;shape shape屬性可以訪問張量的形狀 x.shape # torch.Size([15])2&a…

Wordpress prettyPhoto插件跨站腳本漏洞

漏洞名稱&#xff1a;Wordpress prettyPhoto插件跨站腳本漏洞CNNVD編號&#xff1a;CNNVD-201311-413發布時間&#xff1a;2013-11-28更新時間&#xff1a;2013-11-28危害等級&#xff1a; 漏洞類型&#xff1a;跨站腳本威脅類型&#xff1a;遠程CVE編號&#xff1a; 漏洞來源…

JavaScript學習筆記1

Netscape 公司 DOM模型&#xff0c;層(layer)-用ID標識。 HTML標記頁面上的元素&#xff0c; <div id "mydiv">This is my div</div> CSS為這個頁面元素定位 #mydiv{ position:absolute; left:320px; top:110px; } JavaScript 訪問 (DOM模塊不同&#x…

c# 中關鍵字_C#中的“使用”關鍵字

c# 中關鍵字Prerequisite: Namespace in C# 先決條件&#xff1a; C&#xff03;中的命名空間 If you want to include namespace in a program then we need to use using keyword. For example we use Console class which is defined in System namespace that’s why we n…

C++ 內存基本構件new [] /delete []的意義、內存泄漏原因、VC下cookie的基本布局

目錄一、對new [] delete [] 的理解1、delete的[]遺漏會帶來什么影響二、以示例探討三、cookie的理解一、對new [] delete [] 的理解 new的對象是個array類型的。 Complex* pca new Complex[3]; //喚起三次ctor //無法借由參數給予初值 ... delete[] pca; //喚起3次dtor如下…

OpenJudge計算概論-找出第k大的數

/* 找出第k大的數 總時間限制: 1000ms 內存限制: 1000kB 描述 用戶輸入N和K&#xff0c;然后接著輸入N個正整數&#xff08;無序的&#xff09;&#xff0c;程序在不對N個整數排序的情況下&#xff0c;找出第K大的數。注意&#xff0c;第K大的數意味著從大到小排在第K位的數。并…

01背包怎么不重復_帶有重復物品的背包

01背包怎么不重復Problem statement: 問題陳述&#xff1a; Weights and values are given for n items along with the maximum capacity allowed W. What is the maximum value we can achieve if we can pick any weights, any number of times for the total allowed capa…

jQuery數組處理匯總

有段時間沒寫什么了, 打算把jquery中的比較常用的數組處理方法匯總一下 $.each(array, [callback])遍歷,很常用 ?12345678var arr [javascript, php, java, c, c#, perl, vb, html, css, objective-c];$.each(arr, function(key, val) {// firebug consoleconsole.log(index …

C++ 內存基本構件 placement new

用法以及編譯器解釋 placement new 允許我們將object構建于已經分配的內存上。(所以此時必須有個指針指向已經分配好的內存) 沒有所謂的placement delete &#xff0c;因為placement new根本沒有分配內存. 也有種說法&#xff0c;是將placement new對應的內存釋放掉的操作為pl…

二維數組for遍歷

<?php$conarray(array(1,高某,A公司,北京市,010,abc),array(2,羅某,B公司,天津市,020,bcd),array(3,馮某,C公司,上海市,021,cdf),array(4,書某,D公司,重慶市,022,dfg));echo <table border"1" width"600" align"center">;echo <cap…