【问题标题】:Idenitifying "similar lists" for CodeFights challenge识别 CodeFights 挑战的“相似列表”
【发布时间】:2018-12-12 02:04:20
【问题描述】:

如果一个列表可以通过交换其中一个列表中的最多一对元素从另一个列表中获得,则两个列表称为相似列表。我解决了这个问题,但我需要让它在 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)

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

【问题讨论】:

  • 这是在进行中的比赛吗
  • 你是什么意思??
  • 你说你解决了这个问题,所以这个问题在像 codechef、hackerrank 等正在进行的竞争中也是如此。
  • 已删除——坏主意
  • @Abrar 你说你解决了这个问题,所以这个问题在像 codechef、hackerrank 等正在进行的竞争中也是如此。

标签: python python-3.x list optimization


【解决方案1】:

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

首先,只有长度相同的列表才能相似。一旦您检查了这一点,请检查配对列表一次,注意元素不匹配的位置。如果您发现第三个不匹配,则它们并不相似。如果你以一个不匹配结束,它们就不相似。如果您发现 0 个不匹配,则它们是相似的。

唯一遇到困难的情况是您发现恰好两个元素不匹配的位置。打电话给他们ij。此时,只需检查是否a[i] == b[j] and a[j] == b[i]。返回该比较的结果。

请注意,在此过程中无处您实际上会交换元素。您不需要使列表相同,您只需确定它是否可能具有 0 或 1 交换。

【讨论】:

    【解决方案2】:

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

    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
    

    【讨论】:

    • 太棒了
    • 这样 6/20 测试用例通过 ....其中 10 个是隐藏测试用例,通常它们是非常大的列表
    • @Abrar 你能用这些测试用例的代码更新你的问题,以便我们知道我们在处理什么吗?
    • 这不起作用。简单失败案例:a=[0,1]; b=[0, 1]。另一个简单的失败是a=[0,1]; b=[2, 3]
    • 好多了;不错的工作。这使用了比我的私人解决方案更先进的技术——你的更优雅(Pythonic);我的更接近OP的技术水平。
    【解决方案3】:

    你可以试试这个:-

    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
    

    【讨论】:

    • 测试 1 执行错误:执行解决方案时出现问题 - 程序因错误而意外停止。
    • @Abrar 不要直接使用这段代码;这只是为了说明。
    • @Abrar 尝试用 areSimilar() 代替 check()
    • 对不起,我没有看到支票......它匹配 7......给我一分钟锻炼你的逻辑
    • 这不起作用。它在 a=[0,1]; b=[0, 0] 等情况下失败。
    【解决方案4】:

    它不是很紧凑,但很有效。

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

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

    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))
    

    【讨论】:

      【解决方案5】:

      基于@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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-29
        • 1970-01-01
        • 2021-11-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多