二分查找
二分查找的时间复杂度:logn
1 | bool binary_sort(std::vector<int>& vec, int value) { |
注意循环条件为:left <= right 以及注意 left + right 越界的情况
一、条件
- 二分查找依赖的是顺序表结构,简单点说就是数组
- 其次,二分查找针对的是有序数据。
- 二分查找的底层需要依赖数组这种数据结构,而数组为了支持随机访问的特性,要求内存空间连续,对内存的要求比较苛刻。比如即使我们有 2G 内存,但是是零散的,没有连续的 1G 的内存空间,想要 1G 大小的数组也不行。
- 如何在 1000 万个整数中快速查找某个整数?
每个数据大小 8 个字节,1000万个数据大概是80M,存储在数组中,排序后用二分查找即可。如果内存限制100M,其实是不能用散列表或者二叉树的,因为这些数据结构需要额外的数据结构。
题目
- 求一个数的平方根?先用二分求整数,在用二分求分位数
- 循环有序数组如何使用二分查找?
二分查找的变形
4 中常见的二分查找变形问题
查找第一个值等于给定值的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
if ((mid == 0) || (a[mid - 1] != value)) return mid;
else high = mid - 1;
}
}
return -1;
}查找最后一个值等于给定值的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else if (a[mid] < value) {
low = mid + 1;
} else {
if ((mid == n - 1) || (a[mid + 1] != value)) return mid;
else low = mid + 1;
}
}
return -1;
}查找第一个大于等于给定值的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14public int bsearch(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] >= value) {
if ((mid == 0) || (a[mid - 1] < value)) return mid;
else high = mid - 1;
} else {
low = mid + 1;
}
}
return -1;
}查找最后一个小于等于给定值的元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14public int bsearch7(int[] a, int n, int value) {
int low = 0;
int high = n - 1;
while (low <= high) {
int mid = low + ((high - low) >> 1);
if (a[mid] > value) {
high = mid - 1;
} else {
if ((mid == n - 1) || (a[mid + 1] > value)) return mid;
else low = mid + 1;
}
}
return -1;
}