基于Arm的虚拟手机服务,安装一定数量的App,至少需要多少设备?
最近遇到这么个问题
背景:我们有一些基于Arm架构的虚拟服务器,均已安装Android操作系统,这些虚拟机都可以像我们平常的Android手机一样安装和卸载App。但是安装App时,有两个限制:
1. 和现实中一样,每台虚拟机都有其固定空间,这里我们约定每台虚拟机只能安装不超过t个应用。
2. 每个应用都不能在同一台虚拟机上安装两个
问题:我需要安装n个不同的App到虚拟机上,使用{x1, x2, …., xn}分别表示每个App需要安装的数量,使用t表示每台虚拟设备最多安装的应用数量。那么一共至少需要多少台设备,能满足这样的安装任务?
由于每台设备不能重复安装相同应用,因此,我们不能直接使用
来计算。
我能想到的一个简单的策略就是,利用贪心的思想,一台一台地增加设备,每增加一台设备,尽可能多地安装应用:
1. 为安装任务排序 Sort({x1, x2, …., xn}) = {y1, y2, …, yn}
2. 只要x1+x2+…xn > 0, 就表示还有安装任务没有完成
3. 挑选一台设备,从yn开始向前安装,尽可能地将这台设备装满(要么安装量已经达到t,要么向前找不到一个yk > 0)。 安装上的App的安装量则需要做减一操作,即yn–。
4. 重复1, 2, 3的步骤,直到x1+ x2 + … + xn 等于0。
步骤3中,由于每次尽可能地装满,而且安装的是这些app安装任务中,数量最多的一些任务,因此,能保证剩余的安装任务需要的设备量也是最少的。
虽然算法过程中需要进行多次排序,但个人感觉还是准确及高效的。不知道有没有更好的思路
Java代码实现:
long calExtraDeviceNum(int threshold, List<Long> appExtras) {
int lastIndex = appExtras.size() - 1;
long newNum = 0;
while (listSum.apply(appExtras) > 0) {
Collections.sort(appExtras);
newNum++;
int appsInNewDev = 0;
for (int i = lastIndex; i >= 0 && appsInNewDev <= threshold; i--) {
long needs = appExtras.get(i);
if (needs <= 0) {
break;
} else {
appExtras.set(i, needs - 1);
appsInNewDev++;
}
}
}
return newNum;
}