Python编码挑战中的计时问题

时间:2018-08-28 20:45:39

标签: python python-3.x algorithm time-complexity

我正在尝试解决有关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)

1 个答案:

答案 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的信息,因此某些极端情况可能无法处理。