泡咖啡问题
作者:Grey
原文地址:
题目描述
数组 arr 中记录每个咖啡机制造一杯咖啡的时间,假设有 m 个人,都在 0 号时间点开始排队,返回一个长度为 m 的数组,代表每个人得到咖啡的时间,
要求:最后一个得到咖啡的人的时间尽可能短。
主要思路
定义咖啡机这个数据结构
public static class CoffeeMachine { public int start; public int work; public CoffeeMachine(int s, int w) { start = s; work = w; } @Override public String toString() { return "CoffeeMachine{" + "start=" + start + ", work=" + work + '}'; } }
其中
start 变量表示这个咖啡机什么时候可以空闲,
work 变量表示这个咖啡机制作一杯咖啡的时间,
接下来,设置一个小根堆(Java 中就是 PriorityQueue),小根堆存放的就是咖啡机的信息,小根堆的比较策略就是:咖啡机开始工作的时间加上这个咖啡机制作一杯咖啡的时间之和越小的在堆顶。
每次做完一杯咖啡以后,弹出,记录下此时的时间存入结果数组,并且修改此时的咖啡机的开始工作时间,再次压入小根堆,然后小根堆弹出下一个元素,如此往复,一直到小根堆弹出 m 个元素。
例如

首先把所有咖啡机放入小根堆,第一个弹出的咖啡机是 CoffeeMachine{start=0, work=2}
0 号小人使用 CoffeeMachine{start=0, work=2} 咖啡机
此时这个咖啡机的参数变为 CoffeeMachine{start=2, work=2}
把改变后的咖啡机放入小根堆,再次弹出一个咖啡机,此时
CoffeeMachine{start=0, work=3} 咖啡机被弹出
1 号人使用 CoffeeMachine{start=0, work=3} 咖啡机
此时这个咖啡机的参数变为 CoffeeMachine{start=3, work=3}
把改变后的咖啡机放入小根堆,再次弹出一个咖啡机,此时
CoffeeMachine{start=2, work=2} 咖啡机被弹出
2 号人使用 CoffeeMachine{start=2, work=2} 咖啡机
此时这个咖啡机的参数变为 CoffeeMachine{start=4, work=2}
把改变后的咖啡机放入小根堆,再次弹出一个咖啡机,此时
CoffeeMachine{start=0, work=5} 咖啡机被弹出
3 号人使用 CoffeeMachine{start=0, work=5} 咖啡机
此时这个咖啡机的参数变为 CoffeeMachine{start=5, work=5}
把改变后的咖啡机放入小根堆,再次弹出一个咖啡机,此时
CoffeeMachine{start=4, work=2} 咖啡机被弹出
4 号人使用 CoffeeMachine{start=4, work=2} 咖啡机
此时这个咖啡机的参数变为 CoffeeMachine{start=6, work=2}
完整代码如下
import java.util.PriorityQueue; public class Code_Coffee { public static class CoffeeMachine { @Override public String toString() { return "CoffeeMachine{" + "start=" + start + ", work=" + work + '}'; } public int start; public int work; public CoffeeMachine(int s, int w) { start = s; work = w; } } public static int[] bestChoices(int[] arr, int m) { int[] ans = new int[m]; PriorityQueue<CoffeeMachine> heap = new PriorityQueue<>((o1, o2) -> o1.start + o1.work - o2.start - o2.work); for (int coffeeWork : arr) { // 制造咖啡最短时间的咖啡机在堆顶 heap.add(new CoffeeMachine(0, coffeeWork)); } for (int i = 0; i < m; i++) { CoffeeMachine cur = heap.poll(); // 第i号人使用cur这个咖啡机,所以cur这个咖啡机的开始时间变为cur.start + cur.work System.out.println(i + " 号人使用 " + cur + "咖啡机"); ans[i] = cur.start + cur.work; System.out.println(i + " 号人在 [" + cur.start + "] 时刻搞定完一杯咖啡"); cur.start = ans[i]; heap.add(cur); } return ans; } public static void main(String[] args) { int m = 5; int[] arr = {2, 3, 5}; bestChoices(arr, m); } }