875. Koko Eating Bananas
Koko loves to eat bananas. There are n piles of bananas, the ith pile has piles[i] bananas. The guards have gone and will come back in h hours.
Koko can decide her bananas-per-hour eating speed of k. Each hour, she chooses some pile of bananas and eats k bananas from that pile. If the pile has less than k bananas, she eats all of them instead and will not eat any more bananas during this hour.
Koko likes to eat slowly but still wants to finish eating all the bananas before the guards return.
Return the minimum integer k such that she can eat all the bananas within h hours.
Example 1:
Example 2:
Example 3:
Constraints:
1 <= piles.length <= 104piles.length <= h <= 1091 <= piles[i] <= 109
Solution:
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int left = 1;
int right = 0;
for (int p : piles){
right = Math.max(right, p);
}
int result = right;
while(left <= right){
int mid = left + (right - left) / 2;
if (canFinish(piles, mid, h)){
result = mid;
right = mid - 1;
}else{
left = mid + 1;
}
}
return result;
}
private boolean canFinish(int[] piles, int k, int h){
long time = 0;
for (int p : piles){
time = time + (int) Math.ceil((double) p / k);
if (time > h){
return false;
}
}
return true;
}
}
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int left = 1;
int right = 1;
for (int i = 0; i < piles.length; i++){
right = Math.max(piles[i], right);
}
int result = right;
while (left <= right){
int mid = left + (right - left)/2;
int hourSpent = 0;
for (int pile : piles){
hourSpent += Math.ceil( (double) pile / mid) ;
// hourSpent = (int)(Math.ceil ((double) pile/ mid) + hourSpent);
// 先加 再类型转换, 不然数量越来越大, 精度的差值会导致有些case不通过
}
//Careful here, when we want to get float number of integer devision and round it up
//We need to cast it to float / double first
//But for this problem , Float won't work becasue it can have maximum 6-7 digits
//but the input is maximum 10^9 , so we need to use double here which can have maximum 15 digits
if (hourSpent <= h){
result = Math.min(result, mid);
right = mid-1;
}else{
left = mid + 1;
}
}
return result;
}
}
// TC: O(nlogn)
// SC: O(1)
long是 整数类型(整型),没有小数部分。
double是 浮点数类型(小数)。在 Koko 吃香蕉题里为什么用
long?因为:
time可能很大(n 最多 10^4,每堆最多 10^9)- 用
int可能溢出- 用
long是为了防溢出- 不能用
double,会有精度问题
Ceiling–Floor Conversion Formula
When \(a\) is a non-negative integer and \(b\) is a positive integer, the following identity always holds: $$ \left\lceil \frac{a}{b} \right\rceil = \left\lfloor \frac{a + b - 1}{b} \right\rfloor $$ This is called the “ceiling–floor conversion formula.”
Proof
We consider two cases:
Case 1: \(a \bmod b = 0\)
Then the left side of the identity equals: $$ \frac{a}{b} $$ The right side becomes: $$ \left\lfloor \frac{a + b - 1}{b} \right\rfloor = \left\lfloor \frac{a}{b} + \frac{b - 1}{b} \right\rfloor = \frac{a}{b} + \left\lfloor \frac{b - 1}{b} \right\rfloor = \frac{a}{b} $$ Thus, the identity holds.
Case 2: \(a \bmod b > 0\)
Then the left side equals: $$ \left\lfloor \frac{a}{b} \right\rfloor + 1 $$ Since: $$ \left\lfloor \frac{a}{b} \right\rfloor = \left\lfloor \frac{a - 1}{b} \right\rfloor $$ the right side becomes: $$ \left\lfloor \frac{a - 1 + b}{b} \right\rfloor = \left\lfloor \frac{a - 1}{b} + \frac{b}{b} \right\rfloor = \left\lfloor \frac{a}{b} \right\rfloor + 1 $$ Thus, the identity also holds.
Question & Answer
Question:
Can we use the library function ceil to compute the ceiling directly?
Answer: Doing so converts integers into floating-point numbers, which may introduce rounding errors and cause incorrect results.
For example, the correct value of: $$ \frac{a}{b} = 2 $$ But due to floating-point precision, the computed value might be:
In this case:
- The correct ceiling result is 2
- But applying
ceilto2.000000001would incorrectly give 3
Therefore, using integer arithmetic with the formula: $$ \left\lfloor \frac{a + b - 1}{b} \right\rfloor $$ is safer and more reliable.