classSolution:defsolve(self,piles,k):defpossible(mid): t =0for pile in piles: t += (pile + mid -1) // midreturn t <= k l, r =1,max(piles)while l <= r: mid = (l + r) //2ifpossible(mid): r = mid -1else: l = mid +1return l
JavaScript Code:
functioncanEatAllBananas(piles, H, mid) {let h =0;for (let pile of piles) { h +=Math.ceil(pile / mid); }return h <=H;}/** * @param{number[]} piles * @param{number} H * @return{number} */varminEatingSpeed=function (piles, H) {let lo =1, hi =Math.max(...piles);// [l, r) , 左闭右开的好处是如果能找到,那么返回 l 和 r 都是一样的,因为最终 l 等于 r。while (lo <= hi) {let mid = lo + ((hi - lo) >>1);if (canEatAllBananas(piles,H, mid)) { hi = mid -1; } else { lo = mid +1; } }return lo; // 不能选择hi};
复杂度分析
时间复杂度:$O(max(N, N * logM))$,其中 N 为 piles 长度, M 为 Piles 中最大的数。
空间复杂度:$O(1)$
模板
分享几个常用的的二分法模板。
查找一个数
publicintbinarySearch(int[] nums,int target) {// 左右都闭合的区间 [l, r]int left =0;int right =nums.length-1;while(left <= right) {int mid = left + (right - left) /2;if(nums[mid] == target)return mid;elseif (nums[mid] < target)// 搜索区间变为 [mid+1, right] left = mid +1;elseif (nums[mid] > target)// 搜索区间变为 [left, mid - 1] right = mid -1; }return-1;}