在學習二分查找前,先了解一下順序查找:它對數組逐個掃描,時間複雜度為 O(n),對於大數據量極其低效。二分查找利用有序數組的特性,每次將搜索範圍減半,時間複雜度降為 O(log n),是查找算法的基石之一。
二分查找的邏輯很直觀:
假設:
MyNumArray,長度為 N[First, Last](含首含尾)Mid = (First + Last) / 2Mid_Value = Array[Mid]if (Array[Mid] == MyNum)
return Mid; // 找到,返回索引
if (MyNum < Mid_Value) {
// 新搜索區間:[First, Mid - 1]
Last = Mid - 1; // 關鍵:Last 移動到 Mid - 1
}
注意: 新區間為 [First, Mid - 1],不包含 Mid,因為 Mid 已經比較過了。
if (MyNum > Mid_Value) {
// 新搜索區間:[Mid + 1, Last]
First = Mid + 1; // 關鍵:First 移動到 Mid + 1
}
查找循環在以下兩種情況終止:
First > Last(或 First >= Last 視具體實現),返回「未找到」標識(如 -1)每次循環將問題規模減半,最多需 log₂N 次比較:
理解算法複雜度固然重要,實際測量執行時間能直觀對比不同算法/實現的性能。以下是一個簡易計時器類的設計思路:
class Timer {
public:
Timer(); // 構造函數
void start(); // 開始計時
void stop(); // 停止計時
double time() const; // 返回經過時間(秒)
};
// 使用示例
Timer t;
t.start();
// 執行待測代碼,如 Search()
t.stop();
double elapsed = t.time(); // 獲取耗時(秒)
這樣就能在不依賴外部工具的情況下,快速對比順序查找與二分查找的實際性能差異。
First = Mid + 1 / Last = Mid - 1 是避免死循環的關鍵(First + Last) / 2 可能溢出,建議用 First + (Last - First) / 2「主要是理解,多練。」嘗試手寫迭代版和遞歸版二分查找,並在 LeetCode 等平台練習相關題目(如 704. 二分查找、35. 搜索插入位置、34. 在排序數組中查找元素的第一個和最後一個位置)。