背景:最近在复习本科期间学过的一些数据结构和算法,希望能够对常用的算法做一个提炼和总结,写博客记录一下,供自己回忆,供他人参考,本篇博客主要总结的是整数二分查找算法,列出两个通用模板。
在总结正确模板之前,先根据二分的思路不加思考的写了一段代码,经过测试,这段代码可以运行,但是会有一点小bug,那么发出来的目的一是这是最容易想的思路,也是踩过的一个坑,bug在哪呢?
#include <bits/stdc++.h>
using namespace std;
// 找到的话返回所在下标的位置,没找到则返回-1;
int binSearch(vector<int> nums, int target) {
int l = 0, r = nums.size() - 1;
// 二分查找
while (l < r) {
int mid = (l + r) >> 1;
if (nums[mid] == target) {
return mid; // 找到了则返回target在nums中的下标位置
} else if (nums[mid] > target) {
r = mid - 1;
} else {
l = mid + 1;
}
}
// 没找到返回-1
return -1;
}
int main() {
vector<int> nums = {1, 3, 6, 8, 11, 13, 13, 13, 86, 100};
int ans = binSearch(nums, 13); // bug:当target在nums出现不止一次,则找到并返回的下标有问题
cout << ans << endl;
return 0;
}
模板1:binSearch1
#include <iostream>
#include <vector>
using namespace std;
/* 二分查找模板1:在数组nums中查找target,找到返回下标值,否则返回-1;
注意,若nums中有多个一样的target值,这个模板返回的是第一次找到的target的下标位置;
*/
int binSearch1(vector<int> nums, int target) {
int n = nums.size();
// 定义双指针
int l = 0, r = n - 1;
while (l < r) {
// 二分查找,最后循环终止一定是l == r
int mid = l + r >> 1;
if (nums[mid] >= target) {
r = mid;
} else {
l = mid + 1;
}
}
if (nums[l] != target) {
// 没找到则返回-1
return -1;
}
return l; // 找到返回下标
}
int main() {
vector<int> nums = {1, 3, 6, 8, 11, 13, 13, 13, 86, 100};
int ans = binSearch1(nums, 13);
cout << ans; // 5
return 0;
}
模板2:binSearch2
#include <iostream>
#include <vector>
using namespace std;
/* 二分查找模板2:在数组nums中查找target,找到返回下标值,否则返回-1;
注意,若nums中有多个一样的target值,这个模板返回的是最后一次找到的target的下标位置;
*/
int binSearch2 (vector<int> nums, int target) {
int n = nums.size();
// 定义双指针
int l = 0, r = n - 1;
while (l < r) {
// 二分查找,最后循环终止一定是l == r
int mid = l + r + 1 >> 1; // 此处为什么+1呢?防止陷入死循环,自己举个两个元素的例子试试就懂了,例如nums = {1, 3}, target = 3;
if (nums[mid] <= target) {
l = mid;
} else {
r = mid - 1;
}
}
if (nums[l] != target) {
// 没找到则返回-1
return -1;
}
return l; // 找到返回下标
}
int main() {
vector<int> nums = {1, 3, 6, 8, 11, 13, 13, 13, 86, 100};
int ans = binSearch2(nums, 13);
cout << ans; // 7
return 0;
}
注:俩个模板的主要区别在代码的注释中解释的已经非常清楚了,这里就不再赘述了,不过建议背诵理解第一个模板,也是最常用的最经典的二分查找思路。