常用算法
常用算法
二分查找
三种: 普通 lower_bound upper_bound 找到 = 第一个 >= 第一个 >
进阶
满足二段性即可使用二分查找
不满足时候考虑恢复二段性
判断结果时,可用一个
res直接接收,或者让闭区间的那边是属于结果的.
- 153. 寻找旋转排序数组中的最小值
- 154. 寻找旋转排序数组中的最小值 II
- 33. 搜索旋转排序数组
- 81. 搜索旋转排序数组 II
- 1482. 制作 m 束花所需的最少天数
- 1011. 在 D 天内送达包裹的能力
- 540. 有序数组中的单一元素
- 875. 爱吃香蕉的珂珂
- 1231. Divide Chocolate
前缀和+二分查找
根据元素大于等于0,前缀和数组符合单调不减性, 可以使用二分。
有序集合+二分查找
当元素存在非正时, 可以使用有序集合来二分。
729. My Calendar I
363. 矩形区域不超过 K 的最大数值和
1606. Find Servers That Handled Most Number of Requests
2034. Stock Price Fluctuation
219. Contains Duplicate II
220. Contains Duplicate III
数学
数组\字符串左移\右移
-
先局部后整体是左移,先整体后局部是右移。
其实也可以都先整体,只不过左移就需要调整右边长度为n
二分查找博客
总结的很好, 我也分享一下我了解的吧.
除了楼主提到的模板题, 模板题还有(即C++中的lower_bound和upper_bound函数实现)
1. 直接定义res获取答案
可以避免陷入结果究竟是取
l,l+1下标对应地元素等细节问题, 如29. 两数相除
class Solution {
public:
bool mul(int x, int n, int comp) {
int res = 0;
while (n) {
if (n & 1) {
if (res < comp - x) {
return false;
}
res = res + x;
}
n >>= 1;
if (n == 0)
break;
else if (x < comp - x)
return false;
x += x;
}
return true;
}
int divide(int a, int b) {
if (a == INT_MIN) {
if (b == -1) {
return INT_MAX;
} else if (b == 1) {
return INT_MIN;
}
}
bool rev = false;
if (a > 0) {
a = -a;
rev = !rev;
}
if (b > 0) {
b = -b;
rev = !rev;
}
int l = 0, r = INT_MAX;
int res = 0;
while (l <= r) {
int mid = ((r - l) >> 1) + l;
if (mul(b, mid, a)) {
res = mid; //直接在符合条件的mid处, 设置为res
if (mid == INT_MAX) {
break;
}
l = mid + 1;
} else {
r = mid - 1;
}
}
return rev ? -res : res;
}
};题解本身有点复杂, 理解用res接收答案即可.
当然, 理解到底是哪个下标取答案是很有必要的, 对于二分查找的深入理解必不可少.
2. 二分查找的应用不止于单调性, 符合二段性即可
满足二段性即可使用二分查找
不满足时候可以考虑恢复二段性
通常来说, 需要定义一个check(mid)函数来判断移动left还是right, 如例题
3. 拓展
这部分对二分查找的应用需要对二分查找有一个很深的理解, 给出题目
常用算法
https://messenger1th.github.io/2024/07/24/LeetCode/常用算法/