二分

二分模板

两个模板:1.最大值最小模板一,2.最小值最大用模板二

单调性、两段性的性质

版本1:二分绿色端点是答案,最大值最小

int bsearch_1(int l, int r){
while (l < r){
int mid = l + r >> 1; //下取整
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}

版本2:二分红色端点是答案,最小值最大

int bsearch_2(int l, int r){
while (l < r){
int mid = l + r + 1 >> 1; //上取整
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}

模板2要+1后再下取整

二分最后l和r相等

模板小结:

69. x 的平方根

check性质:t的平方<=x

找最小值最大,模板2

注意精度:long long mid = (long long )(l + (long long ) r + 1) >> 1;

class Solution {
public: bool check(long long mid,int x){
return mid*mid <= x;
} int mySqrt(int x) {
int l = 0,r = x;
while (l < r){
long long mid = (long long )(l + (long long ) r + 1) >> 1;
if(check(mid,x)) l = mid;
else r = mid - 1;
}
return l;
}
};

35. 搜索插入位置

check性质:t>=x,即第一个比x大或等的位置

最大值最小,模板1

class Solution {
public:
bool check(int mid,int x){
return mid >= x;
}
int searchInsert(vector<int>& nums, int target) {
if(nums.size() == 0 || nums.back() < target) return nums.size();
int l = 0,r = nums.size()-1;
while(l<r){
long long mid = (long long )(l + r )>>1;
if(check(nums[mid],target)) r = mid;
else l = mid + 1;
}
return l;
}
};

34. 在排序数组中查找元素的第一个和最后一个位置

两个性质

1.check1:t>=x,找大于等于8的第一个位置,最大值最小,模板1

2.check2:t<=x,找小于等于8的最后1个位置,最小值最大,模板2

class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if(nums.size() == 0) 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[l] != target) return {-1,-1};
int start = l;
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;
}
return {start, l};
}
};

74. 搜索二维矩阵

最大值最小

或者最小值最大,找到目标即可

class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if(matrix.size() == 0 || matrix[0].size() == 0) return false;
int n = matrix.size();
int 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 true;
return false;
}
};

153. 寻找旋转排序数组中的最小值

check性质,nums[mid] <= nums.back() ,且找最大(右半段)满足的最小下标

或者 nums[mid] < nums[0],且找最小值最大

class Solution {
public:
int findMin(vector<int>& nums) {
if(nums.size() == 0) return 0;
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;
}
return nums[r];
}
};

33. 搜索旋转排序数组

思路,按153思路,先找最小值,分成两段;然后按74题思路(最大值最小,且>=target)

两次二分,注意r--后的边界

class Solution {
public:
int search(vector<int>& nums, int target) {
if(nums.size() == 0) 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;
else l = 0,r--;
while(l < r){
int mid = l + r >> 1;
if(nums[mid] >= target) r = mid;
else l = mid + 1;
}
if(target == nums[l]) return l; //这里要用l 否则之前r-- r可能是-1
return -1;
}
};

278. 第一个错误的版本

这道题给了check函数,两段,第一个出错的版本只需要找最大值最小

注意溢出 long long mid = (long long )(l + r >> 1);

// The API isBadVersion is defined for you.
// bool isBadVersion(int version); class Solution {
public:
int firstBadVersion(int n) {
long long l = 1 ,r = n;
while(l < r){
long long mid = (long long )(l + r >> 1);
if(isBadVersion(mid) == true) r = mid;
else l = mid + 1;
}
return r;
}
};

162. 寻找峰值

难度中等190 返回任何一个峰值所在位置即可。

方法1:线性扫描一遍

方法2:二分,比较mid 和 mid+1 如果mid+1的值比mid值大与等于那么mid+1后肯定有峰值,如果mid比mid+1小说明左边或者mid一定存在峰值

边界不需要判,分析:while循环里mid不会等于最后1个点,因为当mid=最后1个点,说明l=r都等于最后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]) l = mid + 1;
else r = mid;
}
return l;
}
};

287. 寻找重复数

只能使用额外的 O(1) 的空间。

时间复杂度小于 O(n^2) 。

二分答案,二分这个数值,O(N)遍历一遍数组统计在Lmid区间内的数的个数,如果个数比区间大小大那么说明有一个重复,重复的数就在这个Lmid闭区间中,让r=mid,否则在左区间(不包含mid)让L=mid+1

class Solution {
public:
int findDuplicate(vector<int>& nums) {
int n = nums.size() - 1;
int l = 1, r = n;
while( l < r){ //二分答案 二分这个数是多少
int mid = l + r >> 1;
int cnt = 0;
for(int i=0;i < nums.size();i++){
if(nums[i] >= l && nums[i] <= mid) cnt++;
}
if(cnt > mid - l + 1) r = mid;
else l = mid + 1;
}
return r;
}
};

275. H指数 II

满足单调性,二分

最小值最大;l最小为0,r最大为n = size个

h满足,h-1也一定满足,可以把区间分成两部分,前一部分红色一定满足,绿色不满足,所以就是找最小值最大

class Solution {
public:
int hIndex(vector<int>& citations) {
int n = citations.size() - 1;
int l = 0, r = citations.size();
while(l < r){
int mid = (l + r + 1) >> 1;
if(citations[n - mid + 1] >= mid) l = mid;
else r = mid - 1;
}
return l;
}
};

LeetCode二分专题的更多相关文章

  1. LeetCode刷题 二分专题

    二分专题 二分的题目类型 对于满足二段性的题目的两套模板 模板一 模板如下 模板二 模板如下 解决二分题目的一般流程 LeeCode实战 LC69.x的平方根 解法思路 LC35.搜索插入位置 解法思 ...

  2. LeetCode 字符串专题(一)

    目录 LeetCode 字符串专题 <c++> \([5]\) Longest Palindromic Substring \([28]\) Implement strStr() [\(4 ...

  3. LeetCode树专题

    LeetCode树专题 98. 验证二叉搜索树 二叉搜索树,每个结点的值都有一个范围 /** * Definition for a binary tree node. * struct TreeNod ...

  4. leetcode二分查找问题整理

    自从做完leetcode上的三道关于二分查找的题后,我觉得它是比链表找环还恶心的题,首先能写出bugfree代码的人就不多,而且可以有各种变形,适合面试的时候不断挑战面试者,一个程序猿写代码解决问题的 ...

  5. leetcode 二分查找

    https://oj.leetcode.com/problems/search-for-a-range/就是一个二分查找,没事练练手 public class Solution { public in ...

  6. 学习笔记--APIO 2018 二分专题 By wuvin

    前言: 在APIO 2018 Day2下午听wuvin讲二分,听了一上午的神仙,现在终于有可以听懂了. 专题: 平均边权最大 题目链接:https://www.questoj.cn/problem/3 ...

  7. Leetcode: 二分搜索法

    package com.LeetCode; /** * 算法:二分搜索法查找一个值,并返回索引值 * https://leetcode.com/problems/search-insert-posit ...

  8. 算法leetcode二分算法

    二分算法通常用于有序序列中查找元素: 有序序列中是否存在满足某条件的元素: 有序序列中第一个满足某条件的元素的位置: 有序序列中最后一个满足某条件的元素的位置. 思路很简单,细节是魔鬼. 一.有序序列 ...

  9. [leetcode]二分查找总结

    Search for a Range 1.最简单的想法,用最普通的二分查找,找到target,然后向左右扩张,大量的重复的target,就会出现O(n)效率. class Solution { pub ...

随机推荐

  1. 在学习java之余,js的使用精髓-闭包和原型链

    这里分享下廖雪峰官网写的js教程,内容写的比较实用,易懂,其中简介的原型链和闭包的知识,小伙伴们一起上呀,畅游在知识的海洋中: 地址:https://www.liaoxuefeng.com/wiki/ ...

  2. Personal Photo Management Application

    Customer Problems & Needs People may take a large number of photos and their phone don't have en ...

  3. vim的常用指令

    vim的常用指令如下: 光标运动: h,j , k, l (上/下/左/右) 删除字符: x 删除行 : dd 模式退出 : Esc,Insert(或者i) 退出编辑器 : q 强制退出不保存: q! ...

  4. css背景渐变色

    张鑫旭关于渐变色博客 菜鸟教程关于渐变色 .img-box{ background: #ec9259; /* 一些不支持背景渐变的浏览器 */ background: -webkit-linear-g ...

  5. 安装宝塔检测到系统已存在Apache,请使用纯净安装

    执行命令 停止服务 net stop Apache2.4 删除服务 sc delete apache

  6. .Net平台GC VS JVM垃圾回收

    前言 不知道你平时是否关注程序内存使用情况,我是关注的比较少,正好借着优化本地一个程序的空对比了一下.Net平台垃圾回收和jvm垃圾回收,顺便用dotMemory看了程序运行后的内存快照,生成内存快照 ...

  7. 动画图解Git命令

    ​Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理,是目前使用范围最广的版本管理工具 尽管Git是一个非常强大的工具,但我认为大多数人都会同意我的说法,即它也可以 ...

  8. Android程序中Acticity间传递数据

    在Android开发过程中,在不同的Acitivity之间传递数据的情况是非常常见的.我花费了一点时间来总结Acitivity之间的数据传递,记录下来. 1.简单传递键值对 这种传递方式非常简单,只需 ...

  9. ES6特性之:参数默认值

    作为一个开发者,跟进行业步伐是非常需要的,不能躺在现有的知识和经验温床上做美梦.JavaScript的ES2015标准(即我们说的ES6)在2016年已经被广泛应用了,还没开始使用的朋友,赶紧来磨一下 ...

  10. 如何设计高并发web应用

      所谓高并发,就是同一时间有很多流量(通常指用户)访问程序的接口.页面及其他资源,解决高并发就是当流量峰值到来时保证程序的稳定性. 我们一般用QPS(每秒查询数,又叫每秒请求数)来衡量程序的综合性能 ...