题目描述
现有一个服务器集群(服务器数量为 serverNum),和一批不同类型的任务(用数组 task表示,下标表示任务类型,值为任务数量)。
现需要把这批任务都分配到集群的服务器上,分配规则如下:
- 应业务安全要求,不同类型的任务不能分配到同一台服务器上
- 一种类型的多个任务可以分配在多台服务器上
「负载」定义为某台服务器所分配的任务个数,无任务的服务器负载为0。
「最高负载」定义为所有服务器中负载的最大值。
请你制定分配方案,使得分配后「最高负载」的值最小,并返回该最小值。
解答要求
时间限制:1000ms, 内存限制:256MB
输入
第一行一个整数,表示集群中服务器的数量 serverNum,1 ≤ serverNum ≤ 10^9
第二行一个整数,表示这批任务有 taskTypeNum 种类型,1 ≤ taskTypeNum ≤ 100000,且 taskTypeNum <= serverNum
第三行输入 taskTypeNum 个整数,为 task 数组,表示这批任务,1 ≤ task[i] ≤ 10^9
输出
一个整数,表示「最高负载」的最小值
样例
输入样例 1 复制
5
2
7 4
输出样例 1
3
提示样例 1
类型 0 的任务有 7 个,可表示为 0000000;类型 1 的任务有 4 个,可表示为 1111 :
- 按 11、11、00、00、000 或 1、111、00、00、000 分配给 5 台服务器,该分配方案的「最高负载」值为 3,是最小的
- 其它方案的「最高负载」值都更大,例如 11、11、0000、000 的「最高负载」为 4
说明:
任务0和任务1不能分配到同一台服务器上。
一次性制定分配方案,不存在二次分配。
输入样例 2
8
5
101 1 1 20 40
输出样例 2
34
提示样例 2
- 如果「最高负载」为 1,需要的服务器台数为 101 + 1 + 1 + 20 + 40 = 163,超过了给定的服务器数量。因此需要尝试更大的「最高负载」值
… - 如果「最高负载」为 33, 需要的服务器台数为 9
- 如果「最高负载」为 34, 需要的服务器台数为 8
- 如果「最高负载」为 35, 需要的服务器台数也为 8
… - 如果「最高负载」为 40, 需要的服务器台数为 7,服务器有浪费
… - 如果「最高负载」为 101, 需要的服务器台数为 5,服务器有更多浪费
所以「最高负载」值最小为 34
温馨提醒:注意计算中的过程值溢出
提示
温馨提醒:纯暴力解法无法通过所有用例
编码实现(Java)
public static void main(String[] args) {
System.out.println(findMinLoad(5, new int[]{7, 4}));
System.out.println(findMinLoad(8, new int[]{101, 1, 1, 20, 40}));
}
private static int findMinLoad(int serverNum, int[] tasks) {
int left = 1; // Minimum load
int right = Arrays.stream(tasks).max().getAsInt() * serverNum; // Maximum load
while (left < right) {
int mid = left + (right - left) / 2;
if (canAssign(tasks, serverNum, mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
private static boolean canAssign(int[] tasks, int serverNum, int maxLoad) {
int requiredServers = 0;
for (int task : tasks) {
requiredServers += (int) Math.ceil((double) task / maxLoad);
}
return requiredServers <= serverNum;
}
输出结果
3
34
Process finished with exit code 0