- Acwing. 789 数的范围【整数二分】">Acwing. 789 数的范围【整数二分】
- Acwing. 790 数的三次方根【浮点数二分】">Acwing. 790 数的三次方根【浮点数二分】
二分查找是针对某个条件,可以把把解空间分为两类,并通过中点所在的类,每次排除一半的解空间。
Acwing. 789 数的范围【整数二分】
该题的题意让我们找到某个数在排序数组中的坐标范围,比如1 2 2 3 3 4。
由于数组是排好序的,因此我们可以考虑二分来做。
首先我们先确定左边界,我们可以把>=target的划分为右类,
如果我们的中点mid在左类,那mid左边包括mid肯定不是我们要求的答案,砍掉。
最终得到左边界。
int get_left(int target) {
int left = 0, right = n - 1;
while(left < right) {
int mid = (left + right) >> 1;
if (d[mid] >= target) {
right = mid;
} else {
left = mid + 1;
}
}
if (d[right] == target) {
return right;
} else {
return -1;
}
}
右边界的求法类似,我们可以把<=target的划分为左类,
如果我们的中点mid在左类,由于我们要求左类最大的数,因此需要砍掉mid左边的数,mid由于可能是最终解,不能排除。
最终得到右边界。
int get_right(int target) {
int left = 0, right = n - 1;
while(left < right) {
int mid = (left + right + 1) >> 1;
if (d[mid] <= target) {
left = mid;
} else {
right = mid - 1;
}
}
if (d[left] == target) {
return left;
} else {
return -1;
}
}
Acwing. 790 数的三次方根【浮点数二分】
浮点数二分和整数二分类似,依旧是根据某个条件,把解空间分成两类,通过中点所在的类排除一半的解空间。
浮点数二分边界情况比整数二分要简单。
#include <iostream>
using namespace std;
int main()
{
double n;
cin >> n;
double left = -10000, right = 10000;
while(right - left > 1e-8) {
double mid = (left + right) / 2;
if (mid * mid * mid >= n) {
right = mid;
} else {
left = mid;
}
}
printf("%.6f", right);
return 0;
}