三分搜尋
目錄
轉自:https://blog.csdn.net/u011787119/article/details/44598871
https://www.cnblogs.com/ECJTUACM-873284962/p/6536414.html
一、概念
在二分查詢的基礎上,在右區間(或左區間)再進行一次二分,這樣的查詢演算法稱為三分查詢,也就是三分法。
三分查詢通常用來迅速確定最值。
二分查詢所面向的搜尋序列的要求是:具有單調性(不一定嚴格單調);沒有單調性的序列不是使用二分查詢。
與二分查詢不同的是,三分法所面向的搜尋序列的要求是:序列為一個凸性函式。通俗來講,就是該序列必須有一個最大值(或最小值),在最大值(最小值)的左側序列,必須滿足不嚴格單調遞增(遞減),右側序列必須滿足不嚴格單調遞減(遞增)。如下圖,表示一個有最大值的凸性函式:
二、演算法過程
如圖所示,已知左右端點L、R,要求找到某點的位置。
思路:通過不斷縮小 [L,R] 的範圍,無限逼近白點。
做法:先取 [L,R] 的中點 midl,再取 [mid,R] 的中點 midr,通過比較 f(midl) 與 f(midr) 的大小來縮小範圍。
當最後 L=R-1 時,再比較下這兩個點的值,我們就找到了答案。
1、當 f(midl) > f(midr) 的時候,我們可以斷定 mmid 一定在白點的右邊。
反證法:假設 mmid 在白點的左邊,則 mid 也一定在白點的左邊,又由 f(midl) > f(midr) 可推出 midl < midr,與已知矛盾,故假設不成立。
所以,此時可以將 R = midr 來縮小範圍。
2、當 f(midl) < f(midr) 的時候,我們可以斷定 mid 一定在白點的左邊。
反證法:假設 midl 在白點的右邊,則 midr 也一定在白點的右邊,又由 f(midl) < f(midr) 可推出 midl > midr,與已知矛盾,故假設不成立。
同理,此時可以將 L = midl 來縮小範圍。
三、程式碼
double f(double x) { // 計算函式值,即f(x) } double trisection_search(double left, double right) { // 三分搜尋,找到最優解(求函式最大值下的自變數值) double midl, midr; while (right-left > 1e-7) { midl = (left + right) / 2; midr = (midl + right) / 2; // 如果是求最小值的話這裡判<=即可 if(f(midl) >= f(midr)) right = midr; else left = midl; } return left; }