如何使用以下约束来加载n个服务器?

时间:2016-11-05 17:20:14

标签: algorithm

这是我在校园实习中向我询问的面试问题之一。

有'n'个服务器分配了一些负载(整数)。我们必须找出分钟。平衡它们所需的时间,使每个服务器上都有负载1。

每个服务器只能与其相邻的邻居(左侧和右侧)共享其负载。

所有服务器上的总负载加起来为n。

实施例。 n = 10
最初,0,0,10,0,0,0,0,0,0,0
时间1:0,1,8,1,0,0,0,0,0,0
时间2:1,1,6,1,1,0,0,0,0,0


时间7:1,1,1,1,1,1,1,1,1,1

答案是7。

最初,服务器上的负载可以以任何方式存在。没有必要它只会出现在我们当前示例中的一台服务器上。

我该如何解决?我无法想出任何方法。

提前致谢

2 个答案:

答案 0 :(得分:3)

对于每台服务器,您需要确定需要向左移动多少负载以及需要向右移动多少。在您的示例中,只有两个作业可以向左移动,因此7个必须向右移动,这需要7个时间段。

如果你有这样的情况

0, 0, 6, 0, 4, 0, 0, 0, 0, 0

然后只有两个可以从6向左移动,所以三个需要向右移动。占据前六个服务器,因此4个作业需要占用最后四个服务器。因此需要5个时间段,因为一个作业需要从4移动到最后一个服务器。

另一个例子,n = 15

0, 0, 0, 3, 0, 0, 0, 0, 4, 0, 0, 6, 2, 0, 0

3需要向左移动,需要3个时间段。 4需要向左移动,需要5个时间段(因为其中一个工作必须占用3个空出的空间)。 6个中的4个工作需要向左移动,需要4个时间段。其中一项工作需要向右移动,需要一段时间。这2个工作需要向右移动,需要2个时间段。答案是5,因为4中的一个工作需要向左移动5个位置。

从这些示例中可以清楚地看出,问题的解决方案是 O(n)解决方案:

int excess = 0;
int answer = 0;
for ( int i = 0; i < N; i++ )
{
    excess = excess + array[i] - 1;
    if ( abs(excess) > answer )
        answer = abs(excess);
}

当工作需要向左移动时,excess为负,而当工作需要向右移动时,excess为正。 answer的绝对值的最大值为GetAllConferences()

答案 1 :(得分:3)

我假设负载总和不超过服务器数量。我的方法是随着时间的推移使用二进制搜索,复杂度为 O(n * logn)

说,我要检查是否可以及时平衡负载 t 。而且我更愿意先将服务器 s 的负载分配给它们的左侧。如果无法将所有负载分配到左侧(因为可能需要超过时间 t 将所有负载分配到左侧或者这些服务器中的一些已经被占用),那么我我要选择右侧的服务器。如果可以在 t 的时间内分配所有负载,那么我将在下一次迭代中选择较小的 t ,否则更高(也称为二进制搜索)。 / p>

bool isBalancableWithin(Time t, Load[] loads) {
    int lastOccupiedIndex = -1;
    foreach (index, loads) {
        int startIndex = max(lastOccupiedIndex + 1, index - t);
        int endIndex   = startIndex + loads[i] - 1;

        if (endIndex > index + t || endIndex >= loads.length) return false;

        lastOccupiedIndex = endIndex;
    }

    return true;
}

Time lowerBound(Load[] loads) {
    Time lowest  = 0;
    Time highest = loads.length;

    while (lowest <= highest) {
        Time mid = (lowest + highest) / 2;

        if (isBalancableWithin(mid, loads)) highest = mid - 1;
        else lowest = mid + 1;
    }

    return lowest;
}