二分查找
- 目标函数具有单调性(单调递增或者递减)
- 存在上下界( b o u n d e d bounded bounded)
- 能够通过索引访问( i n d e x a c c e s s i b l e index \ accessible index accessible)
int left = 0, right = n - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (array[mid] == target) {
// find the target
break or return mid;
}
if (array[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
-
l
o
w
e
r
b
o
u
n
d
lower \ bound
lower bound
- 在单调递增数组里
[10, 14, 19, 25, 27, 31, 33, 35, 42, 44]
,查找第一个 ≥ \geq ≥ 31 的数(返回下标),不存在返回 a r r a y . l e n g t h array.length array.length。
- 在单调递增数组里
-
u
p
p
e
r
b
o
u
n
d
upper \ bound
upper bound
- 在单调递增数组里
[10, 14, 19, 25, 27, 31, 33, 35, 42, 44]
,查找第一个 > > > 26 的数(返回下标),不存在返回 a r r a y . l e n g t h array.length array.length。
- 在单调递增数组里
-
l
o
w
e
r
b
o
u
n
d
lower \ bound
lower bound 和
u
p
p
e
r
b
o
u
n
d
upper \ bound
upper bound 存在的问题是:给定的
target
不一定在数组中存在,array[mid]
即使不等于target
,也可能就是最后的答案,不能随便排除。 - 二分代码三步走:
- 写出二分的条件(一般是一个不等式)。
- 把条件放到 i f if if 里,并确定满足条件时要小的( r i g h t = m i d right = mid right=mid)还是要大的( l e f t = m i d left = mid left=mid)。
- 另一半放到 e l s e else else 里, l e f t = m i d + 1 left = mid + 1 left=mid+1 或 r i g h t = m i d − 1 right = mid - 1 right=mid−1,如果是后者,求 m i d mid mid 时需要 + 1 1 1。如果题目有无解的情况,上界加 1 1 1 或者下界减 1 1 1,用于表示无解。
// 后继型: 查找第一个 >= target 的数, 不存在返回 n
// 改为 array[mid] > target 就是 upper bound
int left = 0, right = n;
while (left < right) {
int mid = (left + right) >> 1;
if (array[mid] >= target) { // 条件满足, 应该被包含
right = mid;
} else {
left = mid + 1;
}
}
return right;
// 前驱型: 查找第一个 <= target 的数, 不存在返回 -1
int left = -1, right = n - 1;
while (left < right) {
int mid = (left + right + 1) / 2;
if (array[mid] <= target) { // 条件满足, 应该被包含
left = mid;
} else {
right = mid - 1;
}
}
return right;
LeetCode 练习题
- 704. 二分查找
- 153. 寻找旋转排序数组中的最小值
- 154. 寻找旋转排序数组中的最小值 II
- 34. 在排序数组中查找元素的第一个和最后一个位置
- 69. x 的平方根
- 74. 搜索二维矩阵
- 240. 搜索二维矩阵 II
- 374. 猜数字大小
三分查找
-
二分法用于在
单调函数
上寻找特定值。
-
三分法用于在
单峰函数
上寻找极大值(或单谷函数上寻找极小值)。- 要求函数是分段严格单调递增
/
/
/递减的(不能出现一段平的情况)。
- 要求函数是分段严格单调递增
/
/
/递减的(不能出现一段平的情况)。
-
以求单峰函数 f f f 的极大值为例,可在定义域 [ l , r ] [l, r] [l,r] 上取任意两点 l m i d lmid lmid, r m i d rmid rmid
- 若 f ( l m i d ) ≤ f ( r m i d ) f(lmid) \leq f(rmid) f(lmid)≤f(rmid),则函数必然在 l m i d lmid lmid 处单调递增,极值在 [ l m i d , r ] [lmid, r] [lmid,r] 上。
- 若 f ( l m i d ) > f ( r m i d ) f(lmid) > f(rmid) f(lmid)>f(rmid),则函数必然在 l m i d lmid lmid 处单调递减,极值在 [ l , r m i d ] [l, rmid] [l,rmid] 上。
- 取
l
m
i
d
lmid
lmid 为二等分点,
r
m
i
d
rmid
rmid 为
l
m
i
d
lmid
lmid 稍加一点偏移量。
LeetCode 练习题