關於二分演算法想必大家也是耳熟能詳,但是在實施演算法時,往往在細節方面由於沒有考慮周全而抓耳撓腮,百思不得其解。這很正常。因為當年在學術界,第乙個正確的二分演算法寫出來就花了20年;又不正常。現在,對於二分演算法無論是理論研究還是實際運用都已經很純熟了,我們既然可以站在巨人的肩膀上,那又何樂而不為呢?
這裡總結一下一些常用的二分演算法的寫法。
查詢序列為嚴格遞增序列,元素所在區間為[0,n-1]。當元素存在重複時,它不保證返回序列中第乙個該元素的索引,故待查詢序列不應存在重複元素。
int
binarysearch
(int l,
int r,
int x)
return-1
;/* 沒有找到,返回-1*/
}
備註1:此處可能存在 l + r 溢位int範圍,所以可以用 l + (r-l)/2避免溢位
lower_bound(求序列中第乙個大於等於目標元素x的索引)
查詢序列為非遞減序列,初始區間為[1,n]——(因為x可能大於序列中所有的元素,此時滿足條件的元素就是其本身,此時返回值為n),
int
lower_bound
(int l,
int r,
int x)
return l;
}
upper_bound(求序列中第乙個大於目標元素x的索引)
查詢序列為非遞減序列,**與與上面類似。
int
lower_bound
(int l,
int r,
int x)
return l;
}
看一道經典題:
給出n個線段長度,試將它們頭尾相接組合成乙個凸多邊形,使凸多邊形的外接圓(多邊形每個頂點都在圓上)的半徑最大,求該最大半徑。其中n<=10^5,線段長度均不超過100,要求演算法中不涉及座標的計算。分析:
思路1首先,因為圓心不確定,想涉及座標計算也無能為力啊?。
其次,考驗數學時候來啦。我們可以確定當圓是凸多邊形外接圓時,該多邊形內角和為π∗(
n−2)
π*(n-2)
π∗(n−2
),對於每一條弦(題中線段),與兩條半徑組成等腰三角形,解該等腰三角形其底角為
α i=
arcc
os(s
i/2r
)α_=arccos(\frac/2})
αi=ar
ccos
(rsi
/2
)則凸多邊形內角和為∑i=
0n−1
αi
\sum_^α_
∑i=0n−
1αi
。此時則可以二分r
rr,當內角和小於誤差限時,即得到最大半徑。
思路2換乙個角度,一條線段(弦)對應的圓心角為
α i=
arcs
in(s
i/2r
)α_=arcsin(\frac/2})
αi=ar
csin
(rsi
/2
)而當r確定,所有的弦對應的圓心角和∑i=
0n−1
αi=2
π\sum_^α_=2π
∑i=0n−
1αi
=2π
,此時可以二分r
rr
二分演算法總結
討論分為3種,第一種是搜尋佇列中任意我們需求的結果,第三種我們需求佇列中有多個返回第乙個,第四種未我們搜尋佇列中有多個返回最後乙個元素的index。第一種 在一行排好序佇列a中搜尋target,一定有。int binarysearch int a,int n,int target return 1 ...
演算法總結 二分查詢
本文首發於我的個人部落格 尾尾部落 二分查詢法作為一種常見的查詢方法,將原本是線性時間提公升到了對數時間範圍,大大縮短了搜尋時間,但它有乙個前提,就是必須在有序資料中進行查詢。二分查詢很好寫,卻很難寫對,據統計只有10 的程式設計師可以寫出沒有bug的的二分查詢 出錯原因主要集中在判定條件和邊界值的...
二分查詢 演算法總結
二分查詢也稱折半搜尋,是一種在有序陣列中查詢某一特定的元素的搜尋演算法。class solution else if nums mid mid left right 2 在left和right都很大的時候會出現溢位的情況,從而導致陣列訪問溢位。改進方法將加法變為減法 mid left right l...