
本文详解 leetcode 第 875 题「koko eating bananas」的标准解法,重点指出新手常犯的两个关键错误:错误计算每堆香蕉所需小时数、以及二分边界更新后返回值逻辑缺陷,并提供完整、可运行的正确实现。
本文详解 leetcode 第 875 题「koko eating bananas」的标准解法,重点指出新手常犯的两个关键错误:错误计算每堆香蕉所需小时数、以及二分边界更新后返回值逻辑缺陷,并提供完整、可运行的正确实现。
在解决「Koko Eating Bananas」问题时,核心目标是找到最小整数吃速 k,使得 Koko 能在 h 小时内吃完所有香蕉。该题天然适合二分查找——吃速 k 越大,总耗时越少;k 越小,耗时越多,且耗时随 k 单调非增,满足二分前提。
但你的原始代码存在两个根本性错误:
❌ 错误一:canEatPiles 逻辑完全错误
你用 Math.ceil((double) sum / capacityPerHour) 计算总耗时,这隐含假设香蕉可以跨堆平均分配——即把所有香蕉混在一起匀速吃。但题目明确要求:每小时只能选一堆,吃掉至多 k 个;若该堆剩余不足 k,则本小时结束,不可转向另一堆继续吃。
例如:piles = [3,6,7,11], k = 4
- 第1小时吃 pile[0]=3 → 吃完,耗时1小时(剩0)
- 第2–3小时吃 pile[1]=6 → 每小时4个,需 ⌈6/4⌉ = 2 小时
- 第4–5小时吃 pile[2]=7 → ⌈7/4⌉ = 2 小时
- 第6–8小时吃 pile[3]=11 → ⌈11/4⌉ = 3 小时
✅ 总计:1 + 2 + 2 + 3 = 8 小时
而你的写法 ⌈(3+6+7+11)/4⌉ = ⌈27/4⌉ = 7,严重低估了实际耗时,导致过早判定 k=4 可行,从而错过更优解或直接出错。
✅ 正确做法:对每堆 p 单独计算耗时 ⌈p / k⌉,即 (p + k - 1) / k(整数上取整技巧),再累加:
private int hoursNeeded(int[] piles, int k) {
int total = 0;
for (int p : piles) {
total += (p + k - 1) / k; // 等价于 Math.ceil((double)p / k)
}
return total;
}❌ 错误二:二分返回值逻辑不严谨
你的代码最后 return mid,但 mid 是循环结束前最后一次计算的中间值,并不保证满足条件。标准二分搜索找「最小可行 k」时,应维护一个候选答案变量,或更稳妥地——循环结束后返回 l。
原因:当 hoursNeeded(k) <= h 时,我们尝试收缩右边界 r = mid - 1 寻找更小的 k;否则 l = mid + 1。最终 l 会停在第一个满足条件的最小 k 上(即左边界突破点),这是二分查找「寻找下界」的标准模式。
✅ 完整修正代码(Java)
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int l = 1;
int r = Arrays.stream(piles).max().orElse(1);
while (l <= r) {
int k = l + (r - l) / 2; // 防止 (l+r) 溢出
if (hoursNeeded(piles, k) <= h) {
r = k - 1; // k 可行,尝试更小的速率
} else {
l = k + 1; // k 不够快,需增大
}
}
return l; // 循环结束时 l 为最小可行 k
}
private int hoursNeeded(int[] piles, int k) {
int total = 0;
for (int p : piles) {
total += (p + k - 1) / k;
}
return total;
}
}⚠️ 关键注意事项
- 时间复杂度:二分范围为 [1, max(piles)],每次验证需 O(n),总复杂度 O(n log(max(piles))),高效且必要。
- 整数上取整技巧:(p + k - 1) / k 是避免浮点运算和 Math.ceil 开销的安全写法,适用于所有正整数 p, k。
- 边界安全:使用 l + (r - l) / 2 替代 (l + r) / 2 防止 l + r 溢出(尤其当 max(piles) 达 10^9 时)。
- 测试验证:务必用例 piles=[3,6,7,11], h=8 手动推演,确认 k=4 时 hoursNeeded=8,k=3 时 hoursNeeded=10 > 8,从而理解为何答案是 4。
掌握这两个修正点,不仅能通过全部 125+ 测试用例,更能深入理解二分查找在“最小化满足条件值”类问题中的标准范式。

















