【题目描述】

珂珂喜欢吃香蕉。这里有 ​​n​​​ 堆香蕉,第 ​​i​​​ 堆中有 ​​piles[i]​​​ 根香蕉。警卫已经离开了,将在 ​​h​​ 小时后回来。

珂珂可以决定她吃香蕉的速度 ​​k​​​ (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 ​​k​​​ 根。如果这堆香蕉少于 ​​k​​ 根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。  

珂珂喜欢慢慢吃,但仍然想在警卫回来前吃掉所有的香蕉。

返回她可以在 ​​h​​​ 小时内吃掉所有香蕉的最小速度 ​​k​​​(​​k​​ 为整数)。

​​​​https://leetcode.cn/problems/koko-eating-bananas/​


【示例】

【LeeCode】875. 爱吃香蕉的珂珂_整除


【代码】​​官方​

向上取整:

1. (int)Math.ceil((double)x/y);
2. pile % speed == 0 ? pile / speed : pile / speed + 1;
3. (speed + pile - 1) / speed;

二分查找方法

package com.company;
// 2023-01-20
class Solution {
public int minEatingSpeed(int[] piles, int h) {
int min = 1;
int max = 1;
for (int pile: piles){
max = Math.max(pile, max);
}
while (min < max){
int mid = (max + min) / 2;
// 如果用时小于h, 满足要求, 缩小窗口
if (check(piles, mid) <= h){
max = mid;
}else {
// 用时过长, 需要提高mid的值
min = mid + 1;
}
}
System.out.println(min);
return min;
}

private int check(int[] piles, int mid) {
int sum = 0;
for (int pile: piles){
// 向上取整: 其他理解: pile % speed == 0 ? pile / speed : pile / speed + 1;
int tmp = (pile + mid - 1) / mid;
sum += tmp;
}
return sum;
}
}
public class Test {
public static void main(String[] args) {
new Solution().minEatingSpeed(new int[]{3,6,7,11}, 8); // 输出: 4
new Solution().minEatingSpeed(new int[]{30,11,23,4,20}, 5); // 输出: 30
new Solution().minEatingSpeed(new int[]{30,11,23,4,20}, 6); // 输出: 23
}
}

【代码】admin

通过用例: 116 / 122   还是利用二分法来进行操作,超时了

package com.company;
// 2022-1-19
import java.util.Arrays;

class Solution {
public int minEatingSpeed(int[] piles, int h) {
// 注意这里最小值是1, 每小时至少吃掉1个
int min = 1;
int max = Arrays.stream(piles).max().getAsInt();
// System.out.println(getMin(piles, min, max, h));
return getMin(piles, min, max, h);
}

private int getMin(int[] piles, int min, int max, int h) {
while (min < max){
int mid = (max + min) / 2;
// 如果刚好满足条件,则直接返回 mid
if (check(piles, mid, h) == h ) {
return mid;
// 如果返回的时间过短,则需要提高mid的值
}else if (check(piles, mid, h) < h ) {
max = mid;
}else {
min = mid + 1;
}
}
// 如果没有,则返回最小的值
return min;
}

private int check(int[] piles, int mid, int h){
// 如果满足条件
int count = 0;
int sum = 0;

for (int i = 0; i < piles.length; i++){
// 题目说了, 小于/等于k 还是会消耗1H
if (piles[i] <= mid) {
count++;
continue;
}
// 计算天数
int shang = piles[i] / mid;
if (count + shang > h) return count + shang;
count += shang;
// 获取剩余的余数
int yushu = piles[i]%mid;
sum += yushu;
}
// 如果剩余的天数可整除, 则累加
int tmp = sum%mid;
if( tmp == 0){
count += sum / mid;
}else {
// 如果剩余的天数不可整除, 则需要多+1
count += sum / mid;
count += 1;
}
// 返回在mid速度下需要的天数
return count;
}
}

public class Test {
public static void main(String[] args) {
new Solution().minEatingSpeed(new int[]{3,6,7,11}, 8); // 输出: 4
new Solution().minEatingSpeed(new int[]{30,11,23,4,20}, 5); // 输出: 30
new Solution().minEatingSpeed(new int[]{30,11,23,4,20}, 6); // 输出: 23
}
}