我正在尝试解决有关Codility的编码挑战问题。问题很简单,如下所示:给定N x M网格我获得的原始代码为here
这是我的改进代码,它更改了第35行和第43行
cnt1 = 0;
cnt2 = 0;
# X = sorted(X);
# Y = sorted(Y);
if (M<1) | (N<1) | (N>100000) | (M>100000) | \
(len(X) % 2 != 0) | (max(X)>= N) | (max(Y) >= M) | (min(X)<0) | (min(Y) < 0) :
return 0
elif (M==1) & (N==1):
return 0
elif (M==1) & (N>=2):
for i in range(N):
y = [X[k] for k, x in enumerate(X) if x <= i]
y2 = [X[k] for k, x in enumerate(X) if x>i]
if(len(y) == len(y2)):
cnt1 = cnt1+1;
else:
cnt1 = cnt1;
return cnt1
elif (N==1) & (M>=2):
for i in range(M):
y = [Y[k] for k, x in enumerate(Y) if x <= i]
y2 =[Y[k] for k, x in enumerate(Y) if x >i]
if(len(y) == len(y2)):
cnt2 = cnt2+1;
else: cnt2 = cnt2
return cnt2
else:
for i in range(N):
y = [X[k] for k, x in enumerate(X) if x <= i]
y2 = [X[k] for k, x in enumerate(X) if x>i] #line 39
if(len(y) == len(y2)):
cnt1 = cnt1+1;
else:
cnt1 = cnt1;
for i in range(M):
y = [Y[k] for k, x in enumerate(Y) if x <= i]
y2 = [Y[k] for k, x in enumerate(Y) if x>i] #line 45
if(len(y) == len(y2)):
cnt2 = cnt2+1;
else:
cnt2 = cnt2
return cnt1 + cnt2
通过上面的代码我将时间复杂度提高了33%,而正确性则为100%(请参见here)。
然后,我继续更改与y2 = set(X).difference(set(y))
和y2 = set(Y).difference(set(y))
相同的两行(35、43),但是在这种情况下,时间复杂度为0%
。正确性也降低到87%
。
问题:有人可以帮我改善上述算法的时间复杂度吗?我很好奇看到您如何避免在此特定问题中使用嵌套的循环(因此,获得O(M+N+K)
)
答案 0 :(得分:1)
通常,当您需要线性复杂度但可以考虑二次解时,请考虑预先计算。
具有更高复杂性的代码:
from itertools import accumulate
# use itertools accumulate to compute prefix sums, it not allowed, can simply write your own function
def solution(N, M, X, Y):
# precompute the mines along rows and cols [O(k)]
rows = [0 for i in range(N)]
cols = [0 for j in range(M)]
for k in range(len(X)):
rows[X[k]]+=1
cols[Y[k]]+=1
# precompute the prefix sum and suffix sum( i.e the total mine grids from left/right upto, including this index ) [O(M+N)]
r_left = list(accumulate(rows))
r_right = list(reversed(list(accumulate(reversed(rows)))))
c_left = list(accumulate(cols))
c_right = list(reversed(list(accumulate(reversed(cols)))))
# now horizontal splits possible at indices where the left and right accumulations are same [O(M+N)]
pos_horizontal_spilts = sum([1 if r_left[i]==r_right[i]-rows[i] else 0 for i in range(N)])
pos_vertical_spilts = sum([1 if c_left[j]==c_right[j]-cols[j] else 0 for j in range(M)])
return pos_horizontal_spilts + pos_vertical_spilts
示例运行:
solution(N = 5, M = 5, X = [0, 4, 2, 0], Y = [0, 0, 1, 4])
rows = [2, 0, 1, 0, 1]
cols = [2, 1, 0, 0, 1]
r_left, r_right = [2, 2, 3, 3, 4], [4, 2, 2, 1, 1]
c_left, c_right = [2, 3, 3, 3, 4], [4, 2, 1, 1, 1]
pos_horizontal_spilts = 2
pos_vertical_spilts = 1
P.S:我尚未提交有关Codility的信息,因此某些极端情况可能无法处理。