一个简单的实现是增加 A 中每个项目的每个范围,但您不需要这样做。您可以首先通过在增量应该开始的位置添加1 和在增量应该停止的位置添加-1 来“准备”您的数组。接下来,您可以计算数组的累积和。喜欢:
def fill_list(la):
lb = [0]*len(la)
n1 = len(la)-1
for i, a in enumerate(la, 1):
xf, xt = i-a, i+a+1
lb[max(0, i-a)] += 1
if xt <= n1:
lb[xt] -= 1
c = 0
for i, b in enumerate(lb):
c += b
lb[i] = c
return lb
或者如果你想返回从 1 到 n 的范围:
def fill_list1(la):
n1 = len(la)
lb = [0]*(n1+1)
for i, a in enumerate(la, 1):
xf, xt = i-a, i+a+1
lb[max(0, i-a)] += 1
if xt <= n1:
lb[xt] -= 1
c = 0
for i, b in enumerate(lb):
c += b
lb[i] = c
return lb[1:]
然后我们可以生成一个列表:
>>> fill_list([1,4,2,5,1,3,0,2])
[4, 4, 4, 5, 5, 5, 4, 3]
>>> fill_list1([1,2,3,4,5])
[5, 5, 4, 4, 3]
因此有以下范围:
-3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 11
--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
|-----|
|-----------------------|
|-----------|
|-----------------------------|
|-----|
|-----------------|
|
|-----------|
--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
0 1 1 1 1 0 0 1 0 0 -1 -1 -1 -2 -1
--*--*--*--*--*--*--*--*--*--*--*--*--*--*--*--
0 1 2 3 4 4 4 5 5 5 4 3 3 1 0
在范围开始之前完成的增量(因此索引小于 0)仅放置在索引 0 以便我们将这些考虑在内。在窗口之后完成的那些(因此索引大于或等于 n 的会被忽略)。
在图像中,第一行显示索引,接下来我们表示来自同一输入的范围,接下来我们显示将放在无限磁带上的增量和减量,接下来我们显示累积和。
算法在O(n)中工作:首先我们以线性时间迭代la,并增加和减少b中的相应元素。接下来我们迭代b,再次在O(n)中计算累积和。