對於兩個二分模板的一些實驗測試
阿新 • • 發佈:2021-07-22
一、總結
1、模板1適合 查詢等於大於目標值的正數第一個值
2、模板2適合 查詢等於小於目標值的倒數第一個值
二、模板1測試(查詢等於大於目標值的第一個值)
#include <bits/stdc++.h> using namespace std; int l, r, k; //排好序的陣列 int a[] = {1, 2, 3, 4, 6, 6, 6, 7, 8, 9, 10}; //符合的性質 bool check(int mid) { return k <= a[mid];//當前選中的mid,它所在位置的數值:a[mid]如果還是大於k的話,那麼需要向左移動 } int main() { cout << "==============================================" << endl; //測試1:如果在陣列中查詢一個肯定存在的數字,比如6這個數,可以找到左側第一個6的位置 l = 0, r = 10, k = 6; //模板1: 查詢等於大於目標值的第一個值 while (l < r) { int mid = (l + r) >> 1; if (check(mid)) r = mid; // 這裡是r=mid, 說明check(mid)返回了true,就是目標值在[l,mid]這個範圍內。 else l = mid + 1; // [l,mid]這個範圍都不是合法範圍,所以下一次查詢直接從 l = mid + 1開始了 //最後的l,r是答案 因為 l == r ,最終就是答案。 } cout << l << " " << r << " " << endl; cout << "==============================================" << endl; //測試2:找出陣列中一個不存在的數字5,看看會發生什麼 l = 0, r = 10, k = 5; //模板1: 查詢等於大於目標值的第一個值 while (l < r) { int mid = (l + r) >> 1; if (check(mid)) r = mid; // 這裡是r=mid, 說明check(mid)返回了true,就是目標值在[l,mid]這個範圍內。 else l = mid + 1; // [l,mid]這個範圍都不是合法範圍,所以下一次查詢直接從 l = mid + 1開始了 //最後的l,r是答案 因為 l == r ,最終就是答案。 } cout << l << " " << r << " " << endl; //找不存在的數字5,它就會多走一個,最終定位在4這個數字上~ return 0; }
三、模板2測試(查詢等於小於目標值的倒數第一個值)
#include <bits/stdc++.h> using namespace std; int l, r, k; //排好序的陣列 int a[] = {1, 2, 3, 4, 6, 6, 6, 7, 8, 9, 10}; //符合的性質 bool check(int mid) { return k >= a[mid];//當前選中的mid,它所在位置的數值:a[mid]如果還是小於k的話,那麼需要向右移動 } int main() { cout << "==============================================" << endl; //測試1:如果在陣列中查詢一個肯定存在的數字,比如6這個數,可以找到右側第一個6的位置 l = 0, r = 10, k = 6; //模板2: 查詢等於小於目標值的倒數第一個值 while (l < r) { int mid = (l + r + 1) / 2; // 這裡要 l + r +1 要不然會死迴圈 if (check(mid)) l = mid; // mid這個位置 滿足條件之後 查詢 [mid , right]的位置, 所以l移到mid的位置 else r = mid - 1; // [mid,r] 不滿足條件, 所以要移到滿足條件的一方, r = mid - 1 } cout << l << " " << r << " " << endl; cout << "==============================================" << endl; //測試2:找出陣列中一個不存在的數字5,看看會發生什麼 l = 0, r = 10, k = 5; //模板2: 查詢等於小於目標值的倒數第一個值 while (l < r) { int mid = (l + r + 1) / 2; // 這裡要 l + r +1 要不然會死迴圈 if (check(mid)) l = mid; // mid這個位置 滿足條件之後 查詢 [mid , right]的位置, 所以l移到mid的位置 else r = mid - 1; // [mid,r] 不滿足條件, 所以要移到滿足條件的一方, r = mid - 1 } cout << l << " " << r << " " << endl; //找不存在的數字5,它就會多走一個,最終定位在4這個數字上~ return 0; }