LeetCode01_二分法专题
一.二分法基本思想
- 二分法做题流程(重要):
- 1.确定二分的边界
- 2.编写二分的代码框架
- 3.设计一个check(性质)
- 4.判断一下区间如何更新
- 5.如果更新方式写的是l = mid, r = mid - 1,那么就在计算mid的时候加上1
二.二分法典型习题
1.LeetCode-69 求解Sqrt(x)
- 解题思路:因为求的是sqrt(x),则x的取值范围是[0, x],因此在此区间中的所有点t均符合性质:t^2 <= x即t <= sqrt(x)
。因此,寻找的是分界点2,采用模板2。class Solution { public:int mySqrt(int x) {int l=0, r = x;while(l < r){int mid = l + (long long)r + 1 >> 1;if (mid <= x / mid) l = mid; // mid * mid <= x;这样写法不好,会出现乘法溢出else r = mid - 1;}return r;} };
2.LeetCode-35 搜索插入位置
- 解题思路:找到大于等于插入元素x的第一个位置,即t >= x,符合模板1
class Solution { public:int searchInsert(vector<int>& nums, int target) {if(nums.empty() || nums.back() < target) return nums.size(); // nums.back() < target:插入的数字比当前数组中所有元素都大,直接返回数组的长度int l = 0, r = nums.size() - 1;while(l < r){int mid = l + r >> 1;if(nums[mid] >= target) r = mid;else l = mid + 1;}return r;} };
3.LeetCode-34 在排序数组中查找元素的第一个和最后一个位置
- 解题思路:使用两次二分算法!确定起始位置:使用性质x >= target来划分整个区间;确定终止位置:使用性质x <= target来划分整个区间。
class Solution { public:vector<int> searchRange(vector<int>& nums, int target) {if(nums.empty()) return {-1,-1};// 确定起始位置int l = 0, r = nums.size() - 1;while(l < r){int mid = l + r >> 1;if(nums[mid] >= target) r = mid;else l = mid + 1;}if(nums[r] != target) return {-1,-1}; // 二分出来的起始位置不等于target,则数组中不存在target这个数int start = r;// 确定终止位置l = 0, r = nums.size() -1 ;while(l < r){int mid = l + r + 1 >> 1;if(nums[mid] <= target) l = mid;else r = mid - 1;}int end = r;return {start, end};} };
4.LeetCode-74 搜索二维矩阵
- 解题思路:给二维矩阵的每个元素进行编号,从0到n*m-1为止,根据题目中的规定,可以将二维矩阵看成是一个严格单调递增的一维数组。选择划分区间的性质x >= target。关键是如何将二维矩阵转换成一维数组,转换公式是j矩阵元素a_ij对应的行下标i=[k/m],列下标j=k%m;其中k是一维数组中的下标。
class Solution { public:bool searchMatrix(vector<vector<int>>& matrix, int target) {if(matrix.empty() || matrix[0].empty()) return false;int n = matrix.size(), m = matrix[0].size();int l = 0, r = n * m - 1;while(l < r){int mid = l + r >> 1;if(matrix[mid / m][mid % m] >= target) r = mid;else l = mid + 1;}if(matrix[r / m][r % m] != target) return false;return true;} };
5.LeetCode-153 寻找旋转排序数组中的最小值
- 解题思路:利用性质target <= nums.back(),可以将区间划分成两段,前一段中所有的元素都大于nums.back(),后一段中所有的元素都符合上面这个性质。
class Solution { public:int findMin(vector<int>& nums) {int l = 0, r = nums.size();while(l < r){int mid = l + r >> 1;if(nums[mid] <= nums.back()) r = mid;else l = mid + 1;}return nums[r];} };
6.LeetCode-33 搜索旋转排序数组
- 解题思路:根据上一题的思路,先利用性质target <= nums.back()确定给定的目标值存在于左边区间还是右边区间。接着利用二分法返回目标值所对应的下标。
class Solution { public:int search(vector<int>& nums, int target) {if(nums.empty()) return -1;int l = 0, r = nums.size() - 1;// 首先找到区间中的最小值,将整个区间划分成左右两段while(l < r){int mid = l + r >> 1;if(nums[mid] <= nums.back()) r = mid;else l = mid + 1;}if(target <= nums.back()) r = nums.size() - 1; // target在后一段区间中// 否则target在前一段区间中else l = 0, r--;while(l < r){int mid = l + r >> 1;if(nums[mid] >= target) r = mid;else l = mid + 1;}if(nums[l] == target) return l;return -1;} };
7.LeetCode-278 第一个错误的版本
- 解题思路:找到第一个错误的版本,则后面的错误版本号一定是大于第一个个错误的版本号,因此性质取的是nums[mid] >= target。
// Forward declaration of isBadVersion API. bool isBadVersion(int version);class Solution { public:int firstBadVersion(int n) {int l = 1, r = n;while(l < r){int mid = (long long)l + r >> 1; // long long防止溢出if(isBadVersion(mid)) r = mid;else l = mid + 1;}return r;} };
8.LeetCode-162 寻找峰值
- 解题思路:属于其他5%的情况,不具有区间的二段性性质。最快的方法时间复杂度是O(logn)。经过分析可知,答案一定在区间当中的。然后,计算区间的中点mid,然后判断mid与mid+1之间的关系,如果nums[mid] < nums[mid+1],则区间[mid+1,r]中一定存在一个答案。反之果nums[mid] > nums[mid+1],同理。
class Solution { public:int findPeakElement(vector<int>& nums) {int l = 0, r = nums.size() - 1;while(l < r){int mid = l + r >> 1;if(nums[mid] > nums[mid + 1]) r = mid;else l = mid + 1;}return r;} };
9.LeetCode-287 寻找重复数
- 解题思路:根据抽屉原理+二分法即可,分别统计[l,mid]和[mid,r]中实际的元素个数(苹果个数),然后因为[l,mid]中一共可以存放的元素个数是mid-l+1(抽屉个数);[mid,r]中一共可以存放的元素个数是r-mid。比较苹果个数和抽屉个数的大小,可以确定重复元素在哪个区间中,每次可以将区间缩小为原来的一半。
class Solution { public:int findDuplicate(vector<int>& nums) {// 抽屉原理 + 二分法可以解决int l = 1, r = nums.size() - 1;while(l < r){int mid = l + r >> 1;int cnt = 0;for(auto x: nums)if(x >= l && x <= mid)cnt++; // 苹果个数cntif(cnt > mid - l + 1) r = mid; // 左半边区间中抽屉个数mid - l + 1else l = mid + 1;}return r;} };
10.LeetCode-275 H指数 II
- 解题思路:找到一个最大的数h,使得数组中至少存在h个数都大于等于h。首先确定边界,h一定是小于等于n(因为当h大于n时假设为n+1,则是找不到最大的数n+1,使得数组中至少存在n+1个数都大于等于n+1),h一定是大于等于0。划分区间性质是:找到一个最大的数h-1,使得数组中至少存在h-1个数都大于等于h-1,即[0,h]条件成立,[h+1,n]条件不成立,n表示元素总数。
class Solution { public:int hIndex(vector<int>& nums) {int l = 0, r = nums.size();while(l < r){int mid = l + r + 1 >> 1;if(nums[nums.size() - mid] >= mid) l = mid;else r = mid - 1;}return l;} };
LeetCode01_二分法专题相关推荐
- 妮妮喜欢吃桃子 java_Leetcode之二分法专题-875. 爱吃香蕉的珂珂(Koko Eating Bananas)...
Leetcode之二分法专题-875. 爱吃香蕉的珂珂(Koko Eating Bananas) 珂珂喜欢吃香蕉.这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉.警卫已经离开了,将在 H ...
- 二分法、三分法 --算法竞赛专题解析(1)
本系列文章将于2021年整理出版,书名<算法竞赛专题解析>. 前驱教材:<算法竞赛入门到进阶> 清华大学出版社 2019.8 网购:京东 当当 作者签名书 如有建议, ...
- c语言二分法查找一个数_算法竞赛小专题系列(1):二分法、三分法
本系列是这本算法教材的扩展资料:<算法竞赛入门到进阶>. 罗勇军.郭卫斌. 清华大学出版社 二分法和三分法是算法竞赛中常见的算法思路,本文介绍了它们的理论背景.模板代码.典型题目. 1. ...
- 算法专题 二分法 普及组【2015】四2 C++版
答案 [分析] 中位数直观定义:有n个数(n为奇数),若存在某数,比它小的数有n/2个,或比它大的数有n个. 转载于:https://www.cnblogs.com/qilinart/articles ...
- 二分法查找平方和_面试手撕系列:二分法
最近春招开始了,面试面着面着一言不合就开始手撕代码手撕就手撕,接下来我打算写几个专题讲讲面试中手撕的常见题目 这些都是LeetCode上有的题目 手撕无非就是 树.链表.二分.字符串这些常用的数据结构 ...
- 二分法求方程的根_快速求解方程的根——二分法与牛顿迭代法
今天是周四高等数学专题的第7篇文章. 之前的文章和大家聊了许多数学上的理论,今天和大家聊点有用的东西. 我们都知道,工业上的很多问题经过抽象和建模之后,本质还是数学问题.而说到数学问题就离不开方程,在 ...
- 微课|中学生可以这样学Python(例8.25):二分法查找
适用教材: 董付国,应根球.<中学生可以这样学Python>.清华大学出版社,2017. 第8章 常用算法的Python实现 例8.25 二分法查找 京东购买链接:https://it ...
- java牛顿法求方程根_快速求解方程的根——二分法与牛顿迭代法
今天是周四高等数学专题的第7篇文章. 之前的文章和大家聊了许多数学上的理论,今天和大家聊点有用的东西. 我们都知道,工业上的很多问题经过抽象和建模之后,本质还是数学问题.而说到数学问题就离不开方程,在 ...
- 【二分法】剑指offer:二维数组中的查找
对于二维数组中每一个一维数组,用二分查找,判断能否找到该数 leetcode专题笔记:二分法查找(1)(附leetcode题)_m0_52043808的博客-CSDN博客 代码: class Solu ...
最新文章
- 特征工程(四)HashingVectorizer
- 海康威视 AI Cloud 软硬件平台
- Day20:绑定方法与非绑定办法、多态和多态性
- windows 建立wifi热点
- mqtt如何判断设备离线_反渗透纯水设备膜元件如何离线清洗?
- Spring Boot 终极清单
- 老男孩教育学员参观机房实践活动
- 华为Mate 30 Pro保护壳生产线谍照曝光:长方形摄像头模组实锤?
- HBuilder实现WiFi调试Android
- MTK刷机(ubuntu下)
- 谈谈杭州市未来15年城市发展重点和杭州第二机场位置预测
- GAEfan qiang教程
- linux监控工具 go实现,Gotop:另一个 TUI 图形活动监视器,使用 Go 编写
- php 使用alert,php中alert函数的用法
- Typora安装 Pandoc实现导出功能
- 目标检测YOLO实战应用案例100讲-基于激光雷达点云的三维目标检测算法研究
- 微信开发者工具调试公众号网页提示: 未绑定为公众号的网页开发者
- Vue中使用v-if判断某个元素满足多个条件的简约写法-案例
- js根据日期生成批次号
- 【人工智能】— 不确定性、先验概率/后验概率、概率密度、贝叶斯法则、朴素贝叶斯 、最大似然估计
热门文章
- 为什么当项目启动后执行两次过滤器 再进行访问资源时执行一次过滤器
- Codeforces Round #562 (Div. 2) B. Pairs
- 单元测试 Mocking 类库需具备的特性
- 利用RGB-D数据进行人体检测 带dataset
- Silverlight 4 WebBrowser的使用及调用 WebBrowser 中的 javascript 方法
- python ctypes库中动态链接库加载方式
- 后台取得客户端控件的值(ListBox)
- Mycat之安全设置与监控工具
- 聊聊底线 | 坏数据与假数据
- 几个简化算法理解的网站,进来收藏!