01_数的范围 number_range
二分查找的边界问题:
(1)查找第一个key: mid向下取整,最后会取到 l,应该靠 l + 1 移动以避免原地无限划分
(2)找最后一个key: mid向上取整,最后会取到 r,应该靠 r - 1 移动以避免原地无限划分
如果直接 l + r 可能导致整数溢出,那么可以: mid = l + (r - l >> 1);
(1)查找第一个和 key 值相等的元素下标
int binary_search(int a[], int n, int key) {
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (a[mid] < key) l = mid + 1;
else r = mid;
}
if (a[l] == key) return l;
return -1;
}
(2)查找最后一个和 key 值相等的元素下标
int binary_search(int a[], int n, int key) {
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (a[mid] > key) r = mid - 1;
else l = mid;
}
if (a[l] == key) return l;
return -1;
}
(3)查找第一个大于等于 key 值的元素下标
int binary_search(int a[], int n, int key) {
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (a[mid] < key) l = mid + 1;
else r = mid;
}
if (a[l] >= key) return l;
return -1;
}
(4)查找最后一个小于等于 key 值的元素下标
int binary_search(int a[], int n, int key) {
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (a[mid] > key) r = mid - 1;
else l = mid;
}
if (a[l] <= key) return l;
return -1;
}
#include <iostream>
using namespace std;
const int N = 100010;
int n, q, k, a[N];
int main() {
cin >> n >> q;
for (int i = 0; i < n; i++) cin >> a[i];
while (q--) {
cin >> k;
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (a[mid] < k) l = mid + 1;
else r = mid;
}
if (a[l] == k) {
cout << l << " ";
r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (a[mid] > k) r = mid - 1;
else l = mid;
}
if (a[r] == k) cout << r << endl;
} else cout << "-1 -1" << endl;
}
return 0;
}
02_数的三次方根 cube_root
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double n;
cin >> n;
double l = -22.0, r = 22.0;
while (l < r - 1e-8) { // l 和 r 只会无限接近,设定一个允许的误差即可
double mid = (l + r) / 2.0;
if (pow(mid, 3.0) < n) l = mid;
else r = mid;
}
printf("%.6lf\n", l);
return 0;
}