在列表中均匀分配(Google Foobar:最大平等)

3
这个问题来自Google Foobar,我的代码通过了除最后一个测试外的所有测试,其中输入/输出被隐藏。
提示:
换句话说,选择数组中的两个元素x [i]和x [j](i不等于j),同时将x [i]增加1并将x [j]减少1。你的目标是尽可能多地使数组中的元素具有相等的值。
例如,如果数组是[1,4,1],则可以执行以下操作:
从第1个车发送兔子到第0个车:增加x [0],减少x [1],结果为[2,3,1]
从第1个车发送兔子到第2个车:增加x [2],减少x [1],结果为[2,2,2]。
现在,数组中所有元素都相等了,你可以向Beta Rabbit报告策略!
请注意,如果数组是[1,2],我们可以获得的最大相等元素数量为1,因为车上的兔子数量永远无法相同。
编写函数answer(x),它接受整数数组x并返回我们可以通过执行上述命令多次获得的最大相等数组元素数量。
火车中的车辆数(x中的元素)至少为2,但不超过100。要共享车的兔子数量(x的每个元素)将是范围内的整数[0,1000000]。
from collections import Counter

def most_common(lst):
    data = Counter(lst)
    return data.most_common(1)[0][1]

def answer(x):
    """The goal is to take all of the rabbits in list x and distribute
    them equally across the original list elements."""
    total = sum(x)
    length = len(x)
    # Find out how many are left over when distributing niavely.
    div, mod = divmod(total, length)
    # Because of the variable size of the list, the remainder
    # might be greater than the length of the list.
    # I just realized this is unnecessary.
    while mod > length:
        div += length
        mod -= length
    # Create a new list the size of x with the base number of rabbits.
    result = [div] * length
    # Distribute the leftovers from earlier across the list.
    for i in xrange(mod):
        result[i] += 1
    # Return the most common element.
    return most_common(result)

在我的测试中,它可以很好地处理一百万次尝试的操作,并且只需要十秒钟左右。但是当输入未知时,它会失败。

我是否忽略了一些显而易见的东西,或者做了我不该做的假设?


你能否稍微注释一下你的代码?我不知道你在做什么。 - Adam Smith
Foobar会告诉你是因为答案错误还是超时而失败吗? - redtuna
@Adam -- 我的理解是,[4, 4, 4] 是正确的解决方案:它提供了三辆具有相同数量的汽车,而不是两辆。 - Prune
@AdamSmith,它明确说明了-“通过根据需要执行上述描述的命令。” 不仅仅是两次。 - Anand S Kumar
1
请再尝试一次编辑,您丢失了代码格式。 - Prune
显示剩余2条评论
1个回答

9
抱歉,但是你的代码在我的测试中无法运行。我输入了 [0, 0, 0, 0, 22],得到了一个 [5, 5, 4, 4, 4] 的列表,答案为 3;最大值应该是 4 辆相同的车,原始输入就是这样一个例子。[4, 4, 4, 4, 6] 是另一个例子。我怀疑这就是你的问题,并且在数据库中可能有很多类似的例子。
对于 N 辆车,最大值要么是 N(如果兔子数量可以被汽车数量整除),要么是 N-1。这似乎很简单,我担心问题中可能有一些限制。它没有要求平衡的人口,只要尽可能多的车辆人口相等即可。简而言之:
def answer(census):
    size = len(census)
    return size if sum(census) % size == 0 else (size-1)

3
哇,干得好。我肯定想多了。非常感谢!(注意:你的代码需要在return语句中添加sum(census)。) - Noah Bogart
1
谢谢。我认为这来自于学习数值分析、数论,并且在学校的普特南考试团队待了两年,再加上从事软件质量保证的职业生涯。我花了很多时间寻找后门。 - Prune
1
问题的说明指出,您应该通过执行上述命令多次(即在 i <> j 的同时从 x[i] 中加或减去,从 x[j] 中减或加)来返回尽可能多的汽车数量。虽然确定兔子数量是奇数还是偶数将分别给出 len(x) - 1 或 len(x),但这并不一定符合问题的精神(实际分配兔子)。 - Austen Hoogen
也许不是,虽然我质疑问题描述中包含多余操作的“精神”。上面的解决方案可以很容易地改变以处理单个移动。首先计算需要在1:(N-1)车中的兔子的目标数量。遍历数组j;每次census[j]>target时,找到最低的i使得census[i]<target。移动兔子直到其中一辆车达到目标值。将饱和索引增加到下一个符合条件的车辆。继续直到倒数第二辆车有目标数量的兔子。 - Prune

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接