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