從這週的習題和每日一題來看,二分查詢雖然思想簡單,但變體眾多,且極易出錯。因此,小結以求避坑。先給出二分查詢模板(c++):參考:王爭老師的專欄 二分查詢(上)
二分查詢(下)
int low = 0;
int high = n - 1;
while (low <= high) else if (a[mid] < value) else
}
其中,關鍵有三點:
迴圈退出條件是 low <= high,而不是 low < high
mid取值,用位運算形式加速,即模板中所示
low 和 high 的更新
至於變體形式,目前所遇到的情況,基本是在如何更新low和high,及在更新的同時完成目標任務上下功夫。這些題目應該是可以直接套用二分查詢模板的,當然這樣可能會囉嗦些,不過也是很好的訓練機會。
再者,什麼時候可以用二分查詢呢?
大抵以下幾點要求:
依靠順序表結構實現,且最好是陣列(鍊錶的話效率太低)
針對的一定是有序資料(起碼得是半有序吧)
更適合處理靜態資料,無頻繁插入刪除為佳
最後,給出四個常用變體形式:
//變體一:查詢第乙個值等於給定值的元素
public int bsearch(int a, int n, int value) else if (a[mid] < value) else
} return -1;
}//變體二:查詢最後乙個值等於給定值的元素
public int bsearch(int a, int n, int value) else if (a[mid] < value) else
} return -1;
}//變體三:查詢第乙個大於等於給定值的元素
public int bsearch(int a, int n, int value) else
} return -1;
}//變體四:查詢最後乙個小於等於給定值的元素
public int bsearch7(int a, int n, int value) else
} return -1;
}
附乙個思考題:使用二分查詢,尋找乙個半有序陣列 [4, 5, 6, 7, 0, 1, 2] 中間無序的地方
//假定為公升序排列且無重複元素,這個問題其實和leetcode 153題(尋找旋轉排序陣列中的最小值)類似
//找出最小元素所在下標,若下標不為0(即非有序陣列),則該下標往後直至陣列末尾都是無序
class solution
low = mid + 1;
}else if (nums[mid] < nums[low])
high = mid - 1;
}else
if (min_num < nums[high])
break;}}
return min_index;
}};
演算法之二分查詢
總時間限制 1000ms 記憶體限制 65536kb 描述在乙個非降序列中,查詢與給定值最接近的元素。輸入第一行包含乙個整數n,為非降序列長度。1 n 100000。第二行包含n個整數,為非降序列各元素。所有元素的大小均在0 1,000,000,000之間。第三行包含乙個整數m,為要詢問的給定值個數...
演算法之二分查詢
二分查詢演算法是運用分治策略的典型例子。給定一組已經排好序的n個元素a n 從這n個元素中找到乙個特定元素x。基本思想 將n 個元素劃分成個數大致相同的兩部分,取中間元素a n 2 與x進行比較 如果x a n 2 即找到x,演算法終止 如果x如果x a n 2 則只在陣列a的右半部分繼續查詢x。c...
演算法之二分查詢
二分查詢針對的是乙個有序的資料集合,查詢思想有點類似分治思想,每次都通過跟區間的中間元素對比,將待查詢的區間縮小為之前的一半,直到找到想要查詢的元素,或是區間被縮小為0。二分查詢的時間複雜度為o l ogn o logn o logn l og nlogn logn 是乙個非常恐怖的數量級,即使n非...