二分法变种小结(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.mzph.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…

小米手环6解决天气未同步问题

最近我发现了我的米6手环天气不同步&#xff0c;打开Zepp Life刷新同步也不行&#xff0c;后来我找了一些网上的解决方法&#xff0c;尝试了一些也还不行&#xff0c;我这人喜欢瞎捣鼓&#xff0c;无意之间给整好了&#xff0c;后来我开始总结自己操作步骤&#xff0c;就在刚才…

C++ 内存分配层次以及memory primitives的基本用法

分配层次 C memory primitives 分配释放类型是否可重载mallocfree()C函数不可newdeleteC表达式不可::operator new()::operator delete()C函数可allocator::allocate()allocator::deallocate()C标准库可自由设计并以之搭配任何容器 分配与释放的四个用法 1、malloc and delet…

一、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++ 内存基本构件new [] /delete []的意义、内存泄漏原因、VC下cookie的基本布局

目录一、对new [] delete [] 的理解1、delete的[]遗漏会带来什么影响二、以示例探讨三、cookie的理解一、对new [] delete [] 的理解 new的对象是个array类型的。 Complex* pca new Complex[3]; //唤起三次ctor //无法借由参数给予初值 ... delete[] pca; //唤起3次dtor如下…

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…

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…

Xcode调试相关小结

一.设置NSZombieEnabled 使用NSZombieEnabled功能,当代码中访问已经释放了内存的地方,会给你下面这样的提示,而不仅仅是EXEC_BAD_ACCESS: 2008-10-03 18:10:39.933 HelloWorld[1026:20b] *** -[GSFont ascender]: message sent to deallocated instance 0x126550 如果要查看上面…

ONGC的完整形式是什么?

ONGC&#xff1a;石油天然气公司 (ONGC: Oil and Natural Gas Corporation) ONGC is an abbreviation of Oil and Natural Gas Corporation. It is an Indian multinational corporation that is one of the leading producers of crude oil and natural gas in India. Its hea…

node 大写_大写Node.js模块

node 大写Today, lets see a third party module that helps us in working with upper-case letters without necessarily typing them in upper-case in our source code. 今天&#xff0c;让我们看一个第三方模块&#xff0c;它可以帮助我们处理大写字母&#xff0c;而不必在…

HDU嵌入式实验课程大作业分析报告

目录作业要求设计原理与思路扩展任务说明课程感受友情链接工程链接作业要求 体能测试记录仪设计 基于课程发放的实验板&#xff0c;设计一个带有计时和数据采集功能的体能测试记录仪。 基本设计内容 功能1&#xff1a;对应1000米体测场景&#xff0c;使用充电宝供电&#x…

html注释引用公共头部_HTML注释和引用

html注释引用公共头部HTML注释 (HTML Comments) To insert a comment in an HTML document, the comment tags are used. The comments are used to provide some information that could be useful for anyone who views the code of the webpage. The comments can be insert…

HDB3码的编码

编码规则 1、源码是1时&#xff0c;暂时不变&#xff1b; 2、连0不超过3个时不变&#xff0c;有4个或以上连0时把每4个0换为取代节&#xff0c;即B00V&#xff1b; 3、确定B是0还是1&#xff1a;第一个B一般取0&#xff0c;若两个取代节之间1的个数为偶&#xff0c;易推得后者…

批量去除文件空格

import osfilepath r"G:\picture" # 文件目录名 allfilepath os.listdir(filepath)for file in allfilepath: # 改目录下的文件名oldpath filepath \\ filenewname file.replace( , ) # 在原先文件名中去除空格&#xff0c;也就是用null替代空格newpath fil…