(二分法進階)三分法超詳解

在使用二分法時必須保證數列是有序的,因此對應到數學問題上實際上解決的是單調函數的求解問題。通過二分法查找其中一個元素key,則轉換爲數學問題求f(x)=key的解。

但是一旦數列不是單調的,那麼二分法就無法使用了,因爲循環判斷中不能確定左右區間的劃分,於是對於函數有凹凸性的情況,便引入了三分法的使用場景。

欲求某個函數的極值點及極值,將區間[l,r]分爲三部分,需要兩個分界點m1和m2,如下
在這裏插入圖片描述
在這裏插入圖片描述
根據上述函數圖像觀察到f(m1)>f(m2),即m2離極小值點更近,爲了讓區間不斷趨近極小值點,r不動,將l趨向m1,所以有l=m1。

在這裏插入圖片描述
在這裏插入圖片描述
當f(m1)<f(m2),即m1點離極小值點更近,此時縮小區間則應讓l不動,r趨近到m2,有r=m2

若f(m1)=f(m2)則同理,爲了簡化代碼,我們在這裏將相等的情況與小於的情況合併

這裏我們求函數的極小值即極小值點來試試,代碼如下:

 /**
     * 函數方程(可自己定義)
     * @param x
     * @return
     */
private static double function(double x){
        return x*x+3*x+6;
    }

    /**
     * 三分法
     * @param l:區間左邊界
     * @param r:區間右邊界
     * @return   極值點的位置
     */
    private static double tripleSearch(double l,double r){
        while(l+EIS<r){           //EIS=10e-6,即10的-6次方;  因爲所有參數爲雙精度型,不能直接用l<r
            double mid1=(l+r)/2;
            double mid2=(mid1+r)/2;
            if(function(mid1)<=function(mid2)){
                 r=mid2;
            }else {
                l=mid1;
            }
        }
        return l;
    }

main函數:

 public static void main(String[] args) {
        System.out.println(String.format("%.2f",tripleSearch(-2,1)));
        System.out.println(String.format("%.2f",function(tripleSearch(-2,1))));
    }

運行結果如下,經過驗算,正確,over!
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章