整数二分查找算法(通用的两个模板)

背景:最近在复习本科期间学过的一些数据结构和算法,希望能够对常用的算法做一个提炼和总结,写博客记录一下,供自己回忆,供他人参考,本篇博客主要总结的是整数二分查找算法,列出两个通用模板。

在总结正确模板之前,先根据二分的思路不加思考的写了一段代码,经过测试,这段代码可以运行,但是会有一点小bug,那么发出来的目的一是这是最容易想的思路,也是踩过的一个坑,bug在哪呢?

#include 
using namespace std;

// 找到的话返回所在下标的位置,没找到则返回-1; 
int binSearch(vector 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 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 
#include 
using namespace std;
/* 二分查找模板1:在数组nums中查找target,找到返回下标值,否则返回-1; 
   注意,若nums中有多个一样的target值,这个模板返回的是第一次找到的target的下标位置; 
*/
int binSearch1(vector 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 nums = {1, 3, 6, 8, 11, 13, 13, 13, 86, 100};
	int ans = binSearch1(nums, 13);
	cout << ans;  // 5 
	return 0;
}

模板2:binSearch2

#include 
#include 
using namespace std;
/* 二分查找模板2:在数组nums中查找target,找到返回下标值,否则返回-1; 
   注意,若nums中有多个一样的target值,这个模板返回的是最后一次找到的target的下标位置; 
*/

int binSearch2 (vector 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 nums = {1, 3, 6, 8, 11, 13, 13, 13, 86, 100};
	int ans = binSearch2(nums, 13);
	cout << ans;  // 7 
	return 0;
}

注:俩个模板的主要区别在代码的注释中解释的已经非常清楚了,这里就不再赘述了,不过建议背诵理解第一个模板,也是最常用的最经典的二分查找思路。

你可能感兴趣的:(数据结构与算法,算法,c++,数据结构)