我如何优化此Python代码?

时间:2018-05-13 00:58:24

标签: python

我正在制作一个接收电话号码列表的代码,然后检查一个或多个号码是否是列表中其他号码的前缀。我想优化到最大,以便它可以尽可能快地运行。这是代码:

cases = []

t = int(input())

for i in range(0, t):
    n = int(input())
    case = []
    for j in range(0, n):
        case.append(str(input()))
    cases.append(sorted(case))

print(cases)

for c in cases:
    answer = 'YES'
    for k in range(0, len(c)):
        if answer == 'YES':
            for l in range(0, len(c)):
                if c[k] != c[l]:            
                    if c[k] == c[l][0:len(c[k])]:
                        answer = 'NO'
                        break
        else:
            break
    print(answer) 

编辑:使用@Gelineau提出的答案,代码运行在0.82秒,即从> 3s到达解决方案之前。现在,解决方案看起来像这样:

cases = []

t = int(input())

for i in range(0, t):
    n = int(input())
    case = []
    for j in range(0, n):
        case.append(str(input()))
    cases.append(case)

for case in cases:
    answer = 'YES'
    case.sort()    
    for case_k, case_next in zip(case, case[1:]):
        if case_k == case_next[:len(case_k)]:
            answer = 'NO'
            break
    print(answer)

2 个答案:

答案 0 :(得分:1)

如果你希望它非常快,那么python很可能不是正确的选择。但你可以做一些小改动,而不是

for i in range(len(c): 
    use c[i] ...

你可以使用

for i in range(len(c): 
    use i ...

同样answer == 'YES'将永远为真,因为当你使它变为假时你会刹车。我最终将代码缩减到了这个:

for case in cases:
    answer = 'YES'
    for case_k, case_l in product(case,case):
        if case_k != case_l and case_k == case_l[:len(case_k)]:
            answer = 'NO'
            break
    print(answer)

你无法真正加速IO,你可以将其改为列表类,但你并没有真正获得任何东西,而且可读性受到很大影响:

cases = [sorted([str(input()) for _ in range(int(input()))]) for _ in range(int(input()))]

编辑:根据@Gelineau留下的评论,我以为我会再给它一次。

但它仍然在O(n ^ 2)时间内增长。

cases = ["".join([input() for _ in range(int(input()))]) for _ in range(int(input()))]
#cases = ['123', '4321', '12345']

for i,case_a in enumerate(cases):
    for case_b in cases[i+1:]:
        if case_b.startswith(case_a):
            print(case_a, "is a prefix")
            break
    else:
        print(case_a, "is not a prefix")

答案 1 :(得分:0)

IMO,由于列表已排序,您可以直接将相邻记录与一个循环进行比较

['2345','1234','123','4567','12345','21234'] => ['123', '1234', '12345', '21234', '2345', '4567']

如果前一记录长度小于当前记录长度且当前第一个X值等于前一记录长度。然后找到并休息。

谢谢