資料結構與演算法之美專欄學習筆記-二分查詢(下)
阿新 • • 發佈:2018-11-12
四種常見的二分查詢變形問題
查詢第一個值等於給定值的元素
//查詢第一個等於給定值的元素 public static int BSearch2(int[] a, int n, int value){ //定義陣列頭尾索引 int low = 0, high = n - 1; //迴圈到頭索引大於等於尾索引 while (low <= high){ //位運算頭尾索引之和除以二得到mid索引,同時避免溢位 int mid = low + ((high - low) >> 1); //根據大小折半比較範圍 if(a[mid] > value) high = mid - 1; else if (a[mid] < value) low = mid + 1; //如果和value相等 else{ //如果mid索引是0,或者mid其前一位不等於value //就說明mid處的資料是第一個和value相等的 if (mid == 0 || a[mid - 1] != value) return mid; //否則就以mid前一位為尾索引進行查詢else high = mid - 1; } } return -1; }
查詢最後一個值等於給定值的元素
//查詢最後一個等於給定值的元素 public static int BSearch3(int[] a, int n, int value){ //定義陣列頭尾索引 int low = 0, high = n - 1; //迴圈到頭索引大於等於尾索引 while (low <= high){ //位運算頭尾索引之和除以二得到mid索引,同時避免溢位 intmid = low + ((high - low) >> 1); //根據大小折半比較範圍 if (a[mid] > value) high = mid - 1; else if (a[mid] < value) low = mid + 1; //如果和value相等 else{ //如果mid索引是n-1,或者mid其後一位不等於value //就說明mid處的資料是最後一個和value相等的 if (mid == n-1 || a[mid + 1] != value) return mid; //否則就以mid後一位為頭索引進行查詢 else low = mid + 1; } } return -1; }
查詢第一個大於等於給定值的元素
//查詢第一個大於等於給定值的元素 public static int BSearch4(int[] a, int n, int value){ //定義陣列頭尾索引 int low = 0, high = n - 1; //迴圈到頭索引大於等於尾索引 while (low <= high){ //位運算頭尾索引之和除以二得到mid索引,同時避免溢位 int mid = low + ((high - low) >> 1); //根據大小折半比較範圍 //若大於value if (a[mid] > value){ //mid為0或者 if (mid == 0 || a[mid - 1] < value) return mid; else high = mid - 1; } else low = mid + 1; } return -1; }
查詢最後一個小於等於給定值的元素
//查詢第一個大於等於給定值的元素 public static int BSearch5(int[] a, int n, int value){ //定義陣列頭尾索引 int low = 0, high = n - 1; //迴圈到頭索引大於等於尾索引 while (low <= high){ //位運算頭尾索引之和除以二得到mid索引,同時避免溢位 int mid = low + ((high - low) >> 1); //根據大小折半比較範圍 //若大於value if (a[mid] < value){ //mid為0或者 if (mid == n-1 || a[mid + 1] > value) return mid; else low = mid + 1; } else high = mid - 1; } return -1; }
適用性分析
凡是能用二分查詢解決的,絕大部分我們更傾向於用散列表或者二叉查詢樹,
即便二分查詢在記憶體上更節省,但是畢竟記憶體如此緊缺的情況並不多。
求“值等於給定值”的二分查詢確實不怎麼用到,二分查詢更適合用在”近似“查詢問題上。比如上面講幾種變體。
思考
如果有一個有序迴圈陣列,比如4,5,6,1,2,3。針對這種情況,如何實現一個求“值等於給定值”的二分查詢演算法?