介绍
三分算法是什么?
三分算法(Ternary Search)是用于在某一个 单峰区间上 寻找最值(最大值或最小值)的一种算法。
- 单峰函数 是指在某一段区间上,函数值先单调上升(或下降),再单调下降(或上升)。
- 适用于连续值(浮点型)或整数值。
特别要注意并不是每个单峰函数都是可以三分的!
某些问题的函数可能是单峰的,但峰值两边并非是严格递增(递减)的,即有可能出现“平台”(一条与 x 轴平行的直线)。
二分算法和三分算法的区别?
特点 | 二分算法 | 三分算法 |
---|---|---|
应用场景 | 查找某个“确定的值” | 查找一个最值(极值) |
单调性要求 | 函数是单调的(增或减) | 函数是单峰的 |
中点数 | 取一个中点 | 取两个中点 mid1 和 mid2 |
目标 | 找一个值/判定某个条件 | 找函数值的最大或最小值 |
三分算法的基本原理
假设你在一条山路上徒步,你想找到最高点(或最低点),这时候你知道地形是单峰的:
-
- 你在区间
[l, r]
中,选取两个点:mid1 = l + (r - l) / 3
,mid2 = r - (r - l) / 3
。
- 你在区间
-
- 计算这两个点的函数值:
f(mid1)
和f(mid2)
- 计算这两个点的函数值:
-
- 比较两者:
- 如果
f(mid1) < f(mid2)
,说明峰值在mid1
到r
之间。 - 如果
f(mid1) >= f(mid2)
,说明峰值在l
到mid2
之间。 - 如果两者相等,也可以缩小区间
[mid1, mid2]
。
-
- 重复这个过程,直到区间非常小,就可以近似找到最值。
板子
单峰函数(凸)函数
double ternary_search(double l, double r) {
while (r - l > 1e-7) {
double mid1 = l + (r - l) / 3;
double mid2 = r - (r - l) / 3;
if (f(mid1) < f(mid2))
l = mid1;
else
r = mid2;
}
return (l + r) / 2;
}
单谷(凹)函数
double ternary_search(double l, double r) {
while (r - l > 1e-7) {
double mid1 = l + (r - l) / 3;
double mid2 = r - (r - l) / 3;
if (f(mid1) > f(mid2))
l = mid1;
else
r = mid2;
}
return (l + r) / 2;
}