【问题标题】:What is the complexity of this algorithm and is there a possibility to improve it?这个算法的复杂度是多少,是否有可能改进它?
【发布时间】:2021-08-15 08:23:56
【问题描述】:

这是本题的算法:写一个函数,以两个数组作为输入,每个数组包含一个A-Z列表;你的程序应该返回 True 如果 第二个数组是第一个数组的子集,否则为 False。

# Python 3 program to find whether an array

def isSubset(arr1, arr2):
    i = 0
    for i in range(len(arr2)):
        if(arr2[i] not in arr1):
            return False
    return True
     
arr1 = ["A", "B", "C", "D", "E", "F"]
arr2 = ["C", "A", "A"]

if(isSubset(arr1, arr2)):
    print("arr2[] is a subset of arr1[] ")
else:
    print("arr2[] is not a subset of arr1[]")

【问题讨论】:

  • 嗨,请阅读 How to ask homework questionOpen letter to students with homework problems 了解如何提出一个好的家庭作业问题。
  • 复杂度是O(n^2) 因为arr2[i] not in arr1 需要O(n) 运行时。
  • 我猜它的 O(n²) 因为你在一个循环中有一个循环。
  • 我相信您的arr1arr2 的输出应该是arr2[] is not a subset of arr1[]
  • O(M*N) 其中 M 和 N 是输入的大小。如果您使用可以更快地检查成员资格的不同数据结构,则可以执行 O(max(M, N))。这里,set 将是选择,python 已经为子集关系实现了小于运算符:set(arr2) <= set(arr1)(注意,<= 是子集,< 是属性子集)

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


【解决方案1】:

您的算法的复杂度是O(n*k),其中nk 是数组的长度。您在另一个循环中有一个循环,在列表中搜索需要O(n)

for i in range(len(arr2)):
     if(arr2[i] not in arr1)  # inner loop because of `in` with `O(n)` complexity

您可以优化您的算法:

s = set()
for el in arr1:
  s.add(el)

for el in arr2:
  if el not in s:
     return False

return True

在这种情况下,时间复杂度为O(n+k),其中nk 是数组的长度。在set 中搜索(并且dict 的时间复杂度为O(1))。

但在这种情况下,您是否需要为set 提供额外的空间。所以新算法的空间复杂度为O(n),而原来的算法是O(1)

【讨论】:

  • ["A", "A", "A"] 的子集["A"]
  • @LearningMathematics 例如:isSubset([A,B,C,D,E], [A,E,D]) = true isSubset([A,B,C,D,E] , [A,D,Z]) = false isSubset([A,D,E], [A,A,D,E]) = true
  • s = set(arr1) 会更短更快。
  • s = () 创建一个空元组。我认为没有任何方法可以在 python 中使用文字创建一个空集,所以你需要s = set()
  • set(arr1).issuperset(arr2) 是单线
【解决方案2】:

我不会为你编写代码,因为这是一道作业题。我会为你描述一个算法,你应该自己实现它。

以你的arr1arr2为例,首先通过存储A-Z的出现次数来预处理arr1。所以对于你的arr1,你应该得到:

"A": 1,
"B": 1,
"C": 1,
"D": 1,
"E": 1,
"F": 1,
"G": 0,
...

现在对arr2 做同样的事情,你应该得到:

"A": 2,
"B": 0,
"C": 1,
"D": 0,
...

现在比较这两个列表中A-Z的值,如果arr2的任何对应值大于arr1,你的程序应该返回false,否则返回true

【讨论】:

    【解决方案3】:

    您的代码的时间复杂度为 O(M*N) - 因为您正在搜索 arr1 中的每个项目是否与 arr2 中的每个项目匹配。

    更好的方法是使用Count 数组并在线性时间和常数空间中求解。

    本准则的复杂性:

    • 时间复杂度:O(M + N)
    • 空间复杂度:O(26)
    arr1 = ["A", "B", "C", "D", "E", "F"]
    arr2 = ["C", "A"]
    
    def check(arr1, arr2):
        c1 = [0]*26
        c2 = [0]*26
        a = ord('A')
        for i in arr1:
            if c1[ord(i) - a] == 0:
                c1[ord(i) - a] += 1
    
        for j in arr2:
            if c2[ord(i) - a] == 0:
                c2[ord(j) - a] += 1
    
        for i in range(len(c1)):
            if c2[i] > c1[i]:
                return 'Not a Subset'
        return 'Subset'
    
    
        
    print(check(["A", "B", "C", "D", "E", "F"], ["C", "A"]))
    print(check(["B"], ["A", "B"]))
    print(check(["A"], ["A", "A"]))
    print(check(["A","B"], []))
    print(check([], []))
    
    Subset
    Not a Subset
    Subset
    Subset
    Subset
    

    【讨论】:

      猜你喜欢
      • 2023-03-07
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多