题解 | #二分查找-I#
二分查找-I
https://www.nowcoder.com/practice/d3df40bd23594118b57554129cadf47b
二分作为一个最为普通且需要我们具备的简单算法
无论在何时何地都有许多的妙用,可以和许许多多的算法加以结合~~~~
而且有衍伸的二分,三分等等.....
首先要明白:
二分的本质是二段性不是单调性。。。。
当想找不满足性质的边界值(红***域的右边界值)
二分左区间的右端点
二分左区间的右端点
- 找中间值 mid = (l+r+1)/2
- if(check(mid))等于true或者是false
- check(m)是检查m是在不满足性质的区间(检查是不是在红***间),更新l或者r
归结上面的两种二分方法,步骤为:
- 先写一个check函数
- 判定在check的情况下(true和false的情况下),如何更新区间。
- 在check(m)==true的分支下是:
r=mid的情况,中间点的更新方式是m=(l+r)/2
这种方法保证了:
1. 最后的l==r
2. 搜索到达的答案是闭区间的,即a[l]是满足check()条件的。
1. 最后的l==r
2. 搜索到达的答案是闭区间的,即a[l]是满足check()条件的。
//#define judge #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 10; int n, q, k; int a[maxn]; int main() { #ifndef judge freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif scanf("%d%d", &n, &q); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); } for (int i = 0; i < q; i++) { scanf("%d", &k); int l = 0, r = n - 1; while (l < r) { int mid = l + r >> 1; if (a[mid] >= k) { r = mid; //第二种情况 找绿***间的左端点 } else { l = mid + 1; } } if (a[l] != k) { printf("-1 -1\n"); } else { printf("%d ", l); l = 0, r = n - 1; while (l < r) { int mid = l + r + 1 >> 1; if (a[mid] <= k) {//第一种情况 找红***间的右端点 l = mid; } else { r = mid - 1; } } printf("%d\n",l); } } return 0; }