python

How can I optmize this Python code?


I'm making a code that receive a list of phone numbers and then checks if one or more of the numbers is a prefix of other numbers in the list. I want to optimize to the maximum so that it can run as fast as possible. Here's the code:

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) 

Edit: Using the answer proposed by @Gelineau, the code run in 0.82s, being that before it went from >3s to reach the solution. With that now the solution looks like this:

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)

Solution

  • ktzr's answer requires n*n comparisons, with n = len(case). You could sort case first (n * log(n) operations), and then you need only compare one case_k with the next one in the list (n operations).

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

    EDITED:

    You can also use a generator expression:

    case.sort()
    answer = all(case_k != case_next[:len(case_k)] for case_k, case_next in zip(case, case[1:]))
    

    (answer will be True or False). It will not be faster, but it is clearer IMHO