数组-差分数组抽象版
超级能吃的珂珂
875. 爱吃香蕉的珂珂 - 力扣(LeetCode)
这玩意是二分查找?不一定再看看,分析一下题目n堆香蕉,速度是变量,速度越快所需时间越少。里面是有一种单调关系。我们要求h小时中吃完,所以可以把这个问题抽象成一个函数,x是吃的速度,y是时间边界条件是h。我们要求的就是边界条件内(y<=h),全吃完的自变量大小(x)。
class Solution {
public:int minEatingSpeed(vector<int>& piles, int h) {int n = piles.size();int left = 1, right = 1000000000 + 1;while(left < right) {int mid = left + (right - left)/2;if(f(piles, mid) == h) {right = mid;} else if(f(piles, mid) > h) {left = mid +1;} else {right = mid;}}return right;}int f(vector<int>& piles, int x) {int hours = 0;for(int& pile : piles) {hours += pile / x;if(pile % x > 0) {hours++;}}return hours;} // 创建一个函数
};
关键点:
1:函数的意义,首先是我们发现了一种单调的关系并且找到了一个边界条件,所以我们考虑可能使用二分,之后求什么什么就是自变量,边界是什么,什么就是函数。通过这个我们可以写出f。
2:我们的二分是基于自变量的,比的时候是基于函数的。自变量的取值范围,也就是吃香蕉的速度,根据题意应该是一到最大的一堆香蕉的数量,所以可以遍历数组找到最大值,也可以直接以题目给的范围作为范围。
3:求解过程中一定要灵活处理,一定要知道函数是增函数还是减函数,可以结合图形理解。主要是两条,我们需要的左边界还是右边界,我们是单调增还是单调减。
1011. 在 D 天内送达包裹的能力 - 力扣(LeetCode)
class Solution {
public:int shipWithinDays(vector<int>& weights, int days) {int left = 0, right = 1;for(const int weight : weights) {left = max(left, weight);right += weight;}while(left < right) {int mid = left + (right - left)/2;if(f(weights, mid) > days) {left = mid+1;} else if(f(weights, mid) == days) {right = mid;} else {right = mid;}}return left;}int f(vector<int>& weights, int x) {int days = 0;int carry = x;for(int& weight : weights) {if(carry < weight) {carry = x;days++;}carry -= weight;}if(carry < x) {days++;}return days;}
};
和上道题基本一样,我们完全按照之前的分析:
关键点:
1:函数的意义,首先是我们发现了一种单调的关系并且找到了一个边界条件,所以我们考虑可能使用二分,之后求什么什么就是自变量,边界是什么,什么就是函数。通过这个我们可以写出f。
总之要求什么什么就是自变量,什么是边界什么就是函数。
2:我们的二分是基于自变量的,比的时候是基于函数的。自变量的取值范围,也就是船的载重,根据题意应该是最大的货物重量到所有货物总重量,所以可以遍历数组找到最大值和sum。
3:求解过程中一定要灵活处理,一定要知道函数是增函数还是减函数,可以结合图形理解。