我們都知道二分查詢演算法,實際上二分查詢以及其擴充套件應用是很廣泛的。這裡收集了一些和二分查詢有關的有趣問題。強烈建議大家看完問題後最小化瀏覽器,先嘗試自己去解決,然後再看**,問題都不是太難。
給乙個已經排序的陣列,其中有n個互不相同的元素。要求使用最小的比較次數找出其中的乙個元素。(你認為二分查詢在排序陣列裡找乙個元素是最優的演算法的嗎?)
不需要太多的理論,這是乙個典型的二分查詢演算法。先看下面的**:
01
// 返回要查詢元素的下標,-1為沒有找到
02
int
binarysearch(
int
a,
int
l,
int
r,
int
key)
03
17
18
return
-1;
19
}
理論上,我們最多需要 logn+1 次比較。仔細觀察,我們在每次迭代中使用兩次比較,除了最後比較成功的一次。實際應用上,比較也是代價高昂的操作,往往不是簡單的資料型別的比較。減少比較的次數也是優化的方向之一。
下面是乙個比較次數更少的實現:
01
// 迴圈不變式: a[l] <= key & a[r] > key
02
// 邊界: |r - l| = 1
03
// 輸入: a[l .... r-1]
04
int
binarysearch(
int
a,
int
l,
int
r,
int
key)
05
16
if
( a[l] == key )
17
return
l;
18
else
19
return
-1;
20
}
在while迴圈中,我們僅依賴於一次比較。搜尋空間( l->r )不斷縮小,我們需要乙個比較跟蹤搜尋狀態。
需要注意的,要保證我們恒等式(a[l] <= key & a[r] > key)正確,後面還會用到迴圈不變式。
給乙個有n個互不相同的元素的已排序陣列,返回小於或等於給定key的最大元素。 例如輸入為 a = key = 7,應該返回6.
分析:我們可以用上面的優化方案,還是保持乙個恒等式,然後移動 左右兩個指標。最終 left指標會指向 小於或等於給定key的最大元素(根據恒等式a[l] <= key and a[r] > key)。
- > 如果陣列中所有元素都小於key,左邊的指標left 會一直移動到最後乙個元素。
- > 如果陣列中所有元素都大於key,這是乙個錯誤條件,無答案。
- > 如果陣列中的所有元素都 <= key,這是最壞的情況根據下面的實現
**:01
// 迴圈不變式: a[l] <= key and a[r] > key
02
// 邊界條件: |r - l| = 1
03
// 輸入: a[l .... r-1]
04
// 先決條件: a[l] <= key <= a[r]
05
int
floor(
int
a,
int
l,
int
r,
int
key)
06
16
return
a[l];
17
}
18
19
// 初始呼叫
20
int
floor(
int
a,
int
size,
int
key)
21
這個函式在c++的stl裡面有實現 : lower_bound 函式
給乙個有重複元素的已排序陣列,找出給定的元素key出現的次數,時間複雜度要求為logn.
分析其實可以對上面的程式稍作修改,思路就是分別找出key 第一次出現的位置和最後一次出現的位置。
01
// 輸入: 陣列區間 [l ... r)
02
// 迴圈不變式: a[l] <= key and a[r] > key
03
int
getrightposition(
int
a,
int
l,
int
r,
int
key)
04
14
return
l;
15
}
16
17
// 輸入: 陣列區間 (l ... r]
18
// 恒等式: a[r] >= key and a[l] > key
19
int
getleftposition(
int
a,
int
l,
int
r,
int
key)
20
30
return
r;
31
}
32
33
int
countoccurances(
int
a,
int
size,
int
key)
34
有乙個已排序的陣列(無相同元素)在未知的位置進行了旋轉操作,找出在新陣列中的最小元素所在的位置。
例如:原陣列 , 旋轉後的陣列可能是 ,也可能是
分析:我們不斷的縮小 l 左指標和 r 右指標直到有乙個元素。把上面劃橫線的作為第一部分,剩下的為第二部分。如果中間位置m落在第一部分,即a[m] < a[r] 不成立,我們排序掉區間 a[m+1 ... r]。 如果中間位置m落在第二部分,即 a[m]01
int
binarysearchindexofminimumrotatedarray(
int
a,
int
l,
int
r)
02
25
return
-1;
26
}
27
28
int
binarysearchindexofminimumrotatedarray(
int
a,
int
size)
29
無處不在的NFC
長期以來,nfc技術處於左右為難或先有雞還是先有蛋的窘境之中。在無產品支援的情況下,製造商為什麼要在手機中採用nfc,反之,當製造商在手機中採用nfc時,為什麼無產品支援?值得慶幸的是,這樣的日子已經一去不復返了,如今已有5億多部支援nfc的高階智慧型手機投入使用,此問題已得到妥善解決。nfc手機正...
無處不在的分析能力
好長時間沒寫部落格了,不是沒有時間,而是堅持的還不夠。今天遇到乙個問題,想寫出來和大家分享。昨天晚上寫到category這個頁面。主要是把類別新增到資料庫中,和從資料庫中拿出後樹狀展示。涉及的知識倒是不多,也就是判斷 迭代等。但是我從昨晚寫,知道今天中午5點才搞定。中間花費了差不多4個小時左右時間來...
無處不在的日期類
所有的類,我們已經寫到目前為止已經足夠簡單,我們已經能夠實現的功能,直接在類本身的定義。例如,我們無處不在的 日期類 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 classdate private defa...