确定CodeFights挑战的“类似列表”

时间:2018-07-03 17:20:33

标签: python python-3.x list optimization

如果可以通过交换其中一个列表中的最多一对元素来从另一个列表中获得一个列表,则将两个列表称为相似列表。我解决了这个问题,但是我需要让它在4秒内针对所有输入运行(Python3)。有什么想法可以提高效率吗?

def areSimilar (a,b):
    counter=0
    for i in range(len(a)):
        for j in range(len(b)):
            if counter < 1 and a[i]!=b[i]:
                if a[i]==b[j]:
                    temp=b[j]
                    b[j]=b[i]
                    b[i]=temp
                    counter+=1
                else:
                    flag=False

    if a == b:
        flag=True
    else:
        flag = False

    return flag

a= [832, 998, 148, 570, 533, 561, 894, 147, 455, 279]
b= [832, 998, 148, 570, 533, 561, 455, 147, 894, 279]
p=areSimilar(a,b)

我认为嵌套循环是我的问题。

5 个答案:

答案 0 :(得分:4)

是的,您的逻辑非常缓慢。没有理由使用嵌套循环:您已经将 O(N)问题变成了 O(N ^ 2)程序。

首先,只有长度相同的列表才能相似。一旦检查完,就遍历配对列表一次,注意元素不匹配的位置。如果您发现第三个不匹配,则它们不相似。如果您一次不匹配就结束了,那就不一样了。如果发现0个不匹配项,则它们相似。

唯一困难更大的情况是,如果您发现恰好两个元素不匹配的位置。分别命名为ij。此时,只需检查是否为a[i] == b[j] and a[j] == b[i]。返回比较结果。

请注意,在此过程中无处实际上会交换元素。您无需使列表完全相同,只需确定交换是0还是1的可能。

答案 1 :(得分:3)

通过两个列表的简单迭代来计算差异数量即可。

import operator
from itertools import zip_longest
def areSimilar(a, b):
    if a == b:
        return True
    diff = list(filter(lambda t: operator.ne(*t), zip_longest(a, b)))
    return len(diff) == 2 and diff[0] == diff[1][::-1]
a= [832, 998, 148, 570, 533, 561, 894, 147, 455, 279]
b= [832, 998, 148, 570, 533, 561, 455, 147, 894, 279]
print(areSimilar(a, b))
print(areSimilar([0, 1], [0, 1]))
print(areSimilar([0, 1], [2, 3]))

这将输出:

True
True
False

答案 2 :(得分:1)

您可以尝试以下操作:-

def areSimilar(a,b):
    if len(a)<2 or len(b)<2:
        return 'Wrong input'
    if len(a) != len(b):
        return False
    if len(a) == len(b) == 2:
        if (a[0] != b[0] and a[0] != b[1]) or (a[1] != b[0] or a[0] != b[1]):
            return False
        else: return True
    var = 0
    for i, j in zip(a,b):
            if i!=j:
                    var += 1
            if var > 2:
                    return False
    if var != 2:
        return False
    return True

>>> a= [832, 998, 148, 570, 533, 561, 894, 147, 455, 279]
>>> b= [832, 998, 148, 570, 533, 561, 455, 147, 894, 279]
>>> areSimilar(a,b)
True

答案 3 :(得分:0)

基于@Prune答案的解决方案。它在4秒内执行,但也许您可以写得更好

def areSimilar (a,b):
    counter=0
    ind1=[]
    ind2=[]
    if len(a) == len(b):
        for i in range(len(a)):
            if a[i] != b[i]:
                counter+=1
                ind1.append(a[i])
                ind2.append(b[i])
                if counter == 2:
                    if ind1[0] == ind2[1] and ind1[1] == ind2[0]:
                        flag= True
                    else:
                        flag = False
    else:
        flag= False

    if counter == 0:
        flag= True
    elif counter ==1 or counter > 2:
        flag=False
    return flag

答案 4 :(得分:-1)

它不是很紧凑,但是可以工作。

由于您正在测试精确位置是否为相同值(最多交换1次),因此可以使用相同的循环。

如果不满足某些条件(例如数组的长度)并且数组甚至包含相同的元素(不包括位置),我已经使下面的代码立即返回。然后,for循环测试位置,并尝试1个2个元素的交换。交换元素的位置必须大于先前测试的位置,因为我们不想重新测试元素。

def areSimilar(a, b):

    flag = False
    swap = False
    if len(a) is not len(b):
        return False

    arrlen = len(a)
    if set(a) == set(b):
        pos1 = None
        pos2 = None
        for i in range(arrlen):
            if a[i] == b[i]:
                flag = True
            else:
                if pos1 is None:
                    if swap is False:
                       swap = True
                       pos1 = i
                       pos2 = b.index(a[i])
                       if pos2 > i:
                           flag = True
                    else:
                        return False
                else:
                    if b[pos1] == a[i]:
                        flag = True
                    else:
                        return False

    return flag


a = [832, 998, 148, 570, 533, 561, 894, 147, 455, 279]
b = [832, 998, 148, 570, 533, 561, 455, 147, 894, 279]
print(areSimilar(a,b))