二分法
作者:
dreams-
,
2024-11-09 16:43:30
,
所有人可见
,
阅读 4
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100005;
int a[N];
int n;
int search_1(int x) {
int l = 0, r = n - 1;
while(l < r) {
int mid = (r - l) / 2 + l;
if(a[mid] >= x) r = mid;
else l = mid + 1;
}
if(a[l] == x) return l;
else return -1;
}
int search_2(int x) {
int l = 0, r = n - 1;
while(l < r) {
int mid = (r - l + 1) / 2 + l;
if(a[mid] > x) r = mid - 1;
else l = mid;
}
if(a[r] == x) return r;
return -1;
}
int main() {
int q;
scanf("%d %d",&n, &q);
for(int i = 0; i < n; ++i) scanf("%d", &a[i]);
while(q--) {
int k; scanf("%d", &k);
int x1 = search_1(k);
int x2 = search_2(k);
printf("%d %d\n",x1, x2);
}
return 0;
}
因为我的个人习惯, 我喜欢使用的临界条件为 left <= right
因为这样的话我可以避免很多麻烦
统一全都是 left = mid - 1, right = mid + 1;
接下来详细解释一下 这种方法的原理 以及 结束循环条件时指针的分布
以及这种题的推广
1、 循环结束的指针分布
此时的 left , right :: left > right
2、 指向 : left 指向 right 指向
(1) 在一串排好序的数据中找出第一个小于 x 的位置 a[r]
在一串排好序的数据中找出第一个出现 x 的位置 a[l] (可能不存在 x)
int l = 0, r = n - 1;
while(l <= r) {
int mid = (r - l) / 2 + l;
if(a[mid] >= x) r = mid - 1;
else l = mid + 1;
}
!!!此时 left 指向第一个 x 或者 第一个大于 x 的值(此时表示数据中没有x)
right 指向 第一个 小于 x 的位置
a[l] = the first x or the first element that is greater than x
a[r] = the first element that is less than x
(2) 在一串排好序的数据中找出第一个大于 x 的位置 a[l]
在一串排好序的数据中找出最后出现的 x 的位置 a[r](可能不存在 x)
int l = 0, r = n - 1;
while(l <= r) {
int mid = (r - l) / 2 + l;
if(a[mid] > x) r = mid - 1;
else l = mid + 1;
}
!!!此时 right 指向最后一个 x 或者 第一个小于 x 的位置(数据中没有x)
left 指向 第一个 大于 x 的位置
a[r] = the last x or the first element that is less than x
a[l] = the first element that is greater than x