【发布时间】: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]) 是给出该值的次数。也就是说,N是A的频率。
现在,我们要做的就是选择最小的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