演算法錄 之 二分和三分

2022-08-31 15:21:11 字數 1780 閱讀 7522

二分:

二分不是二分,是二分。就是一分為二的二分。

先來乙個例子:

現在有乙個遞增的序列 a(1), a(2)...a(n),然後讓你查詢 x 在不在這個序列裡面?

顯然最簡單的做法就是乙個for迴圈,從1到n,看看有沒和x相等的。。。

這樣確實不錯,但是太慢了。。。需要n次才能找到。有沒更好的做法呢?

有(要是沒有的話我說這個幹什麼),那就是二分查詢了。

首先判斷 a(n/2) 和 x 誰大誰小,如果 x 大的話,那麼顯然x可能在 a(n/2+1) 到 a(n) 這個範圍裡面,而一定不會在 a(1) 到 a(n/2) 這個範圍裡面,因為遞增嘛。。。然後再按同樣的方法遞迴查詢後半個區間就行了。

如果x小的話同理找前半個區間。

這樣每次把區間變成原來的一半,那麼就是 logn 級別的時間複雜度,對於長度 n=100000 的序列,只需要不到20次就能判斷x了。。。

具體**如下:

// 查詢a陣列是否存在x。

bool find(int a,int n,int x)

if(a[l]==x) return 1;

return 0;

}

遞增

double calc(double n)

double solve(double l, double r, double v)

return r;}遞減

double calc(double n)

double solve(double l, double r, double v)

return r;

}通俗的說,其實二分是針對乙個單調函式,在這個函式的乙個區間中查詢,每次取區間的中點去判斷,然後根據大小把區間變成原來的一半。。。然後一直這樣下去就好。

二分的應用可以說是很廣很廣。

有乙個典型的應用,就是最大值最小化問題,這類問題一般是要求乙個方案讓所有的數裡面最大的那個最小,然後求這個最小數是多少。

如果是直接硬解的話一般會很困難。所以需要轉換思路。

用二分來試一下。如果先給出乙個上限m之後,要求所有數都不大於m,然後如果存在一種方案的話,說明最後的答案一定比這個數要小於等於,所以二分下去一次次逼近答案就ok了。

題目的話 uva 714 就是經典的二分+貪心問題。

三分:如果說二分針對的是單調函式,那麼三分針對的是雙調函式。也就是下面這樣的函式。

三分是求這樣先增後減或者是先減後增的函式的極值的。

具體步驟就是:對於區間 (l,r),先求出 1/3 處的 m1 和 2/3 處的 m2,然後比較 m1 和 m2 處的大小,如果 m1 處的值大於 m2 處的值,那麼極值一定在(m1,r)這個區間範圍內,否則一定在 (l,m2)這個範圍內。

因為如果 m1處大於m2處的話,m1不可能在極值點的右邊。。。所以。。。就是這樣了。。。每次變成原來區間的2/3大小。。。

二分三分的用處很廣很廣,比如對乙個符合的序列,或者是在計算幾何中用來求一些不好算的值等等。。。

比如求點到橢圓的最近距離的題目,就可以通過三分一次次的逼近。

const double eps = 1e-10;

double calc(double n)

double solve(double l, double r)

return l;

}

二分和三分

三分二分,乙個簡單而神奇的演算法,可以簡化時間複雜度,但是用二分有乙個條件,就是我們進行二分的序列必須有單調性。原理 aa中找乙個數x xx 保證x xx一定存在 我們可以用樸素演算法,直接從頭到尾找一遍,時間複雜度o n o n o n 如果當序列a aa的長度十分大時,這種方法就不好用了。二分橫...

二分和三分

二分 二分,即為折半查詢,它是一種效率較高的查詢方法。但是,折半查詢要求線性表必須採用順序儲存結構,而且表中元素按關鍵字有序排列。也就是說,二分的條件為必須滿足數列或某一邏輯的順序性,單調 只有這樣才能進行二分。查詢方法 首先,假設表中元素是按公升序排列,將表中間位置記錄的關鍵字與查詢關鍵字比較,如...

二分和三分

二分查詢 二分的精度問題,一般用double解決,eps 1e 8,關於l,r的取值看那個區間有沒有可能取到,然後 1或者 1,會不會使得值變化得特別大,如果會變化得特別大,那麼就l,r都取mid o log n 查詢乙個數 int b search int x return 1 查詢左邊界 int...