二分查找
可以二分的前提:有序
时间复杂度:O(log n)
模板
目前只遇到了两种二分情况,基本可以包括所有二分的情景:
-
前半段是false,后半段是true,查找最靠左的true
形如:false false false false true true true
实例:对于升序数组,查找第一个大于等于target的元素的下标
1
2
3
4
5
6
7
8int l = 0, r = n - 1;
while(l <= r){
int mid = (l + r) >> 1;
if(nums[mid] >= target)
r = mid - 1;
else l = mid + 1;
}
return l; -
前半段是true,后半段是false,查找最靠右的true
形如:true true true false false
实例:对于降序数组,查找最后一个大于等于target的元素的下标
1
2
3
4
5
6
7
8int l = 0, r = n - 1;
while(l <= r){
int mid = (l + r) >> 1;
if(nums[mid] >= target)
l = mid + 1;
else r = mid - 1;
}
return r;
while判断条件始终是小于等于,l和r始终是mid往右/往左一步。需要最靠哪边的true,就返回哪边的指针,即靠左对应return l
;靠右对应return r
;在不确定返回l还是r时,可以举例子,模拟一下l和r最终的指向。
二分答案
对于求极小值的极大值问题,通常可以转化为在有序数组中求最靠左/最靠右的true的问题,进而可以转化为二分查找问题。
给你一个整数数组 nums
,其中 nums[i]
表示第 i
个袋子里球的数目。同时给你一个整数 maxOperations
。
你可以进行如下操作至多 maxOperations
次:
- 选择任意一个袋子,并将袋子里的球分到 2 个新的袋子中,每个袋子里都有正整数个球。
- 比方说,一个袋子里有
5
个球,你可以把它们分到两个新袋子里,分别有1
个和4
个球,或者分别有2
个和3
个球。
- 比方说,一个袋子里有
你的开销是单个袋子里球数目的 最大值 ,你想要 最小化 开销。
请你返回进行上述操作后的最小开销。
示例 1:
1 | 输入:nums = [9], maxOperations = 2 |
分析:随着开销的增大,操作数ops会减小,因此对开销进行二分,找到满足ops <= maxOperations
的最小开销,即最靠左的true。可以想象一个数组以开销为索引,其值前半段是false,后半段是true。
代码:
1 | class Solution { |
__END__