一.二分法基本思想

  • 二分法做题流程(重要):

    • 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_二分法专题相关推荐

  1. 妮妮喜欢吃桃子 java_Leetcode之二分法专题-875. 爱吃香蕉的珂珂(Koko Eating Bananas)...

    Leetcode之二分法专题-875. 爱吃香蕉的珂珂(Koko Eating Bananas) 珂珂喜欢吃香蕉.这里有 N 堆香蕉,第 i 堆中有 piles[i] 根香蕉.警卫已经离开了,将在 H ...

  2. 二分法、三分法 --算法竞赛专题解析(1)

    本系列文章将于2021年整理出版,书名<算法竞赛专题解析>. 前驱教材:<算法竞赛入门到进阶> 清华大学出版社 2019.8 网购:京东 当当      作者签名书 如有建议, ...

  3. c语言二分法查找一个数_算法竞赛小专题系列(1):二分法、三分法

    本系列是这本算法教材的扩展资料:<算法竞赛入门到进阶>. 罗勇军.郭卫斌. 清华大学出版社 二分法和三分法是算法竞赛中常见的算法思路,本文介绍了它们的理论背景.模板代码.典型题目. 1. ...

  4. 算法专题 二分法 普及组【2015】四2 C++版

    答案 [分析] 中位数直观定义:有n个数(n为奇数),若存在某数,比它小的数有n/2个,或比它大的数有n个. 转载于:https://www.cnblogs.com/qilinart/articles ...

  5. 二分法查找平方和_面试手撕系列:二分法

    最近春招开始了,面试面着面着一言不合就开始手撕代码手撕就手撕,接下来我打算写几个专题讲讲面试中手撕的常见题目 这些都是LeetCode上有的题目 手撕无非就是 树.链表.二分.字符串这些常用的数据结构 ...

  6. 二分法求方程的根_快速求解方程的根——二分法与牛顿迭代法

    今天是周四高等数学专题的第7篇文章. 之前的文章和大家聊了许多数学上的理论,今天和大家聊点有用的东西. 我们都知道,工业上的很多问题经过抽象和建模之后,本质还是数学问题.而说到数学问题就离不开方程,在 ...

  7. 微课|中学生可以这样学Python(例8.25):二分法查找

    适用教材: 董付国,应根球.<中学生可以这样学Python>.清华大学出版社,2017. 第8章  常用算法的Python实现 例8.25  二分法查找 京东购买链接:https://it ...

  8. java牛顿法求方程根_快速求解方程的根——二分法与牛顿迭代法

    今天是周四高等数学专题的第7篇文章. 之前的文章和大家聊了许多数学上的理论,今天和大家聊点有用的东西. 我们都知道,工业上的很多问题经过抽象和建模之后,本质还是数学问题.而说到数学问题就离不开方程,在 ...

  9. 【二分法】剑指offer:二维数组中的查找

    对于二维数组中每一个一维数组,用二分查找,判断能否找到该数 leetcode专题笔记:二分法查找(1)(附leetcode题)_m0_52043808的博客-CSDN博客 代码: class Solu ...

最新文章

  1. 特征工程(四)HashingVectorizer
  2. 海康威视 AI Cloud 软硬件平台
  3. Day20:绑定方法与非绑定办法、多态和多态性
  4. windows 建立wifi热点
  5. mqtt如何判断设备离线_反渗透纯水设备膜元件如何离线清洗?
  6. Spring Boot 终极清单
  7. 老男孩教育学员参观机房实践活动
  8. 华为Mate 30 Pro保护壳生产线谍照曝光:长方形摄像头模组实锤?
  9. HBuilder实现WiFi调试Android
  10. MTK刷机(ubuntu下)
  11. 谈谈杭州市未来15年城市发展重点和杭州第二机场位置预测
  12. GAEfan qiang教程
  13. linux监控工具 go实现,Gotop:另一个 TUI 图形活动监视器,使用 Go 编写
  14. php 使用alert,php中alert函数的用法
  15. Typora安装 Pandoc实现导出功能
  16. 目标检测YOLO实战应用案例100讲-基于激光雷达点云的三维目标检测算法研究
  17. 微信开发者工具调试公众号网页提示: 未绑定为公众号的网页开发者
  18. Vue中使用v-if判断某个元素满足多个条件的简约写法-案例
  19. js根据日期生成批次号
  20. 【人工智能】— 不确定性、先验概率/后验概率、概率密度、贝叶斯法则、朴素贝叶斯 、最大似然估计

热门文章

  1. 为什么当项目启动后执行两次过滤器 再进行访问资源时执行一次过滤器
  2. Codeforces Round #562 (Div. 2) B. Pairs
  3. 单元测试 Mocking 类库需具备的特性
  4. 利用RGB-D数据进行人体检测 带dataset
  5. Silverlight 4 WebBrowser的使用及调用 WebBrowser 中的 javascript 方法
  6. python ctypes库中动态链接库加载方式
  7. 后台取得客户端控件的值(ListBox)
  8. Mycat之安全设置与监控工具
  9. 聊聊底线 | 坏数据与假数据
  10. 几个简化算法理解的网站,进来收藏!