【问题标题】:The Game of Piles桩的游戏
【发布时间】:2021-12-16 10:15:32
【问题描述】:

最近我遇到了一个似乎很有趣的游戏,它建议在大型数据集上同时实现两指针和前缀和技术。这是任务本身:

假设有一个长度为 k 的数组 v,其中 k (kA(所谓的堆)和N(数量),例如:

k = 3
v = [[2, 2], [3, 2], [2, 1]]

A (v[i][0]) 是值,N (v[i][1]) 是给出该值的次数。也就是说,NA的频率。

现在,我们要做的就是选择最小的A,从列表的两端开始,从当前位置减去它,然后添加到后面的位置。然后我们继续这样做,直到中间只剩下两个或一个etries。也就是说,每一步我们选择最小的一堆,然后从两端减去,直到剩下一两堆。

答案应该包括两行:第一行包含“1”或“2”,具体取决于剩余的桩数,第二行是结果本身。

为简化起见,我们可以将堆表示为如下所示的普通列表:

v = [2, 2, 3, 3, 2] 

我们从左端和右端(2)中选择最小值,减去它并添加到下一个值:

v = [0, 4, 3, 5, 0]

4和5的最小值是4,所以我们减去4,得到两堆。

v = [0, 0, 11, 1, 0]

输出是:

2
11 1

我的代码是:

k = int(input())
a = []
for _ in range(k):
    A, N = map(int, input().split())
    x = [A] * N
    a += x


l = 0
r = len(a)-1
while r - l > 1:
    s = min(a[l], a[r])
    a[l] -= s
    a[r] -= s
    a[l+1] += s
    a[r-1] += s
    if a[l] == 0:
       l += 1
    if a[r] == 0:
       r -= 1

if a[r] == 0 or a[r]==a[l]:
    print(1)
    print(a[l])
      
else:
    print(2)
    print(a[l], a[r])

此解决方案在 k = 10**5 时未能达到时间限制(2 秒),因为它需要将数组转换为普通列表,并且几乎不使用前缀和。我确信有一个更快的解决方案,它带有前缀和、附加变量和存储一个给定的数组。对于如何加快此代码速度的任何建议,我将不胜感激。
为了防止任何与语言相关的 cmets:该游戏适用于任何编程语言,因此时间限制不是 python 的具体问题。

【问题讨论】:

  • 尝试一种不涉及扩展数组的方法;它仍应使用您已实现的相同算法(左右两个指针),但在增量/减法操作中需要更加小心。

标签: python algorithm pointers big-o prefix-sum


【解决方案1】:

我不会给你答案,但我会给出一个推理出答案的路径。

诀窍不是更快地执行算法,而是在做更少的工作的同时找出应用算法的结果。为了让这更容易,我将用更慢的算法替换算法,这恰好更容易推理。

与其从两边减去较小的,加到下一个,让我们只从每边减去 1,加到下一个。所以你的例子会开始:

[2, 2, 3, 3, 2]
[1, 3, 3, 4, 1]
[0, 4, 3, 5, 0]
...

让我们开始推理吧。

首先假设我们在一端有A,需要多少步才能将那一端向前推进?答案很简单A

如果我们有 A 后跟 k as 会发生什么?前进通过块直到所有东西都堆在最后一个元素上需要

A + A+a + A+2a + ... A+(k-1)a
    = kA + (1 + 2 + ... + (k-1))a
    = kA + k(k-1)a/2

此时最后一个元素现在具有A + ka 元素。

所以现在,无需扩展块,我们可以通过一个简单的公式计算出通过它需要多少工作。我们也可以在另一边这样做。因此,在不扩展的情况下,我们可以开始消耗每一侧的整个块,直到我们在最后 2 或 3 个块遇到中间。然后我们必须小心,但是当另一方完成一个块时,我们可以准确地确定一个在哪里。然后我们可以将这些块分成更小的块元素并继续前进,直到我们在前进的前沿之间找到最多 3 个数组元素,它们将相遇。然后我们将原始算法应用几次以获得确切的答案。

但是您必须能够通过一次算术计算来遍历整个块,以使其足够快。

祝你所有的边界条件都正确!

【讨论】:

  • 我想你的公式让我想起算术级数并不是巧合。我将尝试解决并在此处发布答案,非常感谢!
猜你喜欢
  • 1970-01-01
  • 2015-06-12
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多