二分查找模板(c++)

模板一:
二分查找的最基础和最基本的形式。
查找条件可以在不与元素的两侧进行比较的情况下确定(或使用它周围的特定元素)。
不需要后处理,因为每一步中,你都在检查是否找到了元素。如果到达末尾,则知道未找到该元素。

int binarySearch(vector<int>& nums, int target){
  if(nums.size() == 0)
    return -1;

  int left = 0, right = nums.size() - 1;
  while(left <= right){
    // 防止left + right溢出,使用 left + (right - left) / 2
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid - 1; }
  }

  // left > right时结束循环
  return -1;
}

模板二(最值问题可套用该模板):
一种实现二分查找的高级方法。
查找条件需要访问元素的直接右邻居。
使用元素的右邻居来确定是否满足条件,并决定是向左还是向右。
保证查找空间在每一步中至少有 2 个元素。
需要进行后处理。 当你剩下 1 个元素时,循环 / 递归结束。 需要评估剩余元素是否符合条件。

int binarySearch(vector<int>& nums, int target){
  if(nums.size() == 0)
    return -1;

  int left = 0, right = nums.size();
  while(left < right){
    int mid = left + (right - left) / 2;
    if(nums[mid] == target){ return mid; }
    else if(nums[mid] < target) { left = mid + 1; }
    else { right = mid; }
  }

  // left == right终止循环,当数组元素小于2个时需进行后处理
  if(left != nums.size() && nums[left] == target) return left;
  return -1;
}

参考自力扣点我传送

例题:打包(可套用模板2)

试题 算法提高 打包
     
资源限制
内存限制:256.0MB   C/C++时间限制:1.0s   Java时间限制:3.0s   Python时间限制:5.0s
问题描述
  Lazy有N个礼物需要打成M个包裹,邮寄给M个人,这些礼物虽然很便宜,但是很重。Lazy希望每个人得到的礼物的编号都是连续的。为了避免支付高昂的超重费,他还希望让包裹的最大重量最小。
输入格式
  一行两个整数N和M。
  一行N个整数,表示N个礼物的重量。
输出格式
  一个整数,表示最小的最大重量。
样例输入
3 2
1 1 2
样例输出
2
数据规模和约定
  N, M <= 100,000
  重量 <= 1,000

原题传送阵
分析:让包裹的最大重量最小,最大中的最小和最小中的最大考虑二分法求。
此题最小值就是单个包裹重量的最大值,最大值是所有包裹重量和
判断每个包裹最大重量为mid时能否分成m份,若超过m份则最大重量小了,l=mid+1,否则r=mid

#include<bits/stdc++.h>
using namespace std;
const int M = 100003;
int n, m, a[M], all_wei, max_wei;
int main() {
	cin >> n >> m;//n个礼物 给m个人 
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		all_wei += a[i];
		if (a[i] > max_wei)max_wei = a[i];
	}
	int l = max_wei, r = all_wei;
	while (l < r) {
		int mid = l + (r - l) / 2;
		int parcel = 0, k = 1;
		for (int i = 1; i <= n; i++) {
			parcel += a[i];
			if (parcel > mid) {
				k++;
				parcel = a[i];
			}
		}
		if (k <= m)r = mid;
		else l = mid + 1;
	}
	cout << l;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苓一在学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值