算法 C++二分搜索

二分搜索

时间复杂度
O(logN):最坏的情况下
O(1):恰好要找的数在最中间

寻找一个数

要点:数组是有序

bool exist(vector<int>& arr, int num)
{
	if (arr == null || arr.size() == 0) {
		return false;
	}
	
	int l = 0, r = arr.size() - 1;
	int mid = 0;
	while (l <= r) {
		mid = (l + r) / 2;
		if (arr[mid] > num) { // 中间值比要找的值还要大,说明arr[mid]后面的值都比num大,缩小右边界
			r = m - 1; 
		}
		else if (arr[mid] < num) { // 中间值比要找的值还要小,说明arr[mid]前面的值都比num大,扩大左边界
			l = m + 1;
		}
		else {
			return true;
		}
	}
	return false;
} 

寻找有序数组中找>=num的最左位置

int findLeft(vector<int>& arr, int num)
{	
	int l = 0, r = arr.size() - 1;
	int mid = 0;
	int ans = -1;
	while (l <= r) {
		mid = l + ((r - l) >> 1);
		if (arr[mid] >= num) { // 中间值比要找的值还要大,说明arr[mid]后面的值都比num大,缩小右边界
			ans = m;
			r = m - 1; 
		}
		else {
			l = m + 1;
		}
	}
	return ans;
} 

有序数组中找<=num的最右位置

int findLeft(vector<int>& arr, int num)
{	
	int l = 0, r = arr.size() - 1;
	int mid = 0;
	int ans = -1;
	while (l <= r) {
		mid = l + ((r - l) >> 1);
		if (arr[mid] <= num) {  // 中间值比要找的值还要小,说明arr[mid]前面的值都比num大,扩大左边界
			ans = m;
			l = m + 1;
		}
		else {
			r = m - 1; 
		}
	}
	return ans;
} 

寻找峰值

要点:二分搜素并不只是用到有序数组

一个数组 [3,2,11,4,5,13,6,7]

峰值:中间的值大于两边的值,只看相邻的值

1 2 0 数组里面 2 就是峰值

寻找一个数组里面的第一个峰值:
1.设 -1 位置为一个特别小的值,设置 arr.size() + 1 的位置为一个很小的值
2.求 0 位置的值大于 1 位置的值
3.求 arr.size() - 1的值 大于 arr.size() - 2的值
4.求 1 ~ arr.size() - 2之间的峰值

当数组两边都是极小值的时候
最左边也就是 -1位置的值是 < 0位置的值,呈上升趋势。
最右边的值,arr.size() 位置的值,< arr.size() - 1位置的值,呈下降趋势。
一升一降,就会产生峰值。

int findPeakElement(vector<int>& arr) {
	int n = arr.size();
	if (arr.size() == 1) {
		return 0;
	}
	if (arr[0] > arr[1]) {
		return 0;
	}
	if (arr[n - 1] > arr[n - 2]) {
		return n - 1;
	}
	int l = 1, r = n - 2, mid = 0,ans = -1; 
	while (l <= r) {
		mid = l + ((r - l) >> 1);
		if (arr[mid - 1] > arr[mid]) {
			r = mid - 1;
		}
		else if (arr[mid] < arr[mid + 1]) {
			l = mid + 1;
		}
		else {
			ans = mid;
			break;
		}
	}
	return ans;
}
posted @ 2025-08-27 22:51  杰西卡若  阅读(5)  评论(0)    收藏  举报