【问题标题】:Can an algorithm with higher Complexity be Faster?具有更高复杂性的算法可以更快吗?
【发布时间】:2022-01-04 19:34:33
【问题描述】:

我已经为一个问题编写了一个代码,并在实现中使用了 2 个双嵌套循环,但是这个代码运行时间太长,大 O 为 O(n^2)。

所以我搜索了一个更快的解决方案来解决同样的问题,并找到了下面的第二个代码,它使用了一个三重嵌套循环,大 O 为 O(n^3)。

是不是因为第一个代码的计算次数较高,尽管它的大 O 较低?

如果是这样,我是否可以得出结论,对于小的“n”值,大 O 不可靠,我必须进行实验才能判断?

代码 1:

def sherlockAndAnagrams(s):
    # 1 . Traverse all possible substrings within string
    count = 0
    lst_char_poss_str = []
    len_s = len(s)
    
    for i in range(len_s):#for each char in string
        temp_str = ""#a temp string to include characters next to evaluating char
        
        for j in range(i , len_s):#for all possible length of string from that char
            temp_str += s[j] #possible substrings from that char
            lst_char_poss_str.append(temp_str)#All possible substrings within string
    
    # 2 . Check if any two substrings of equal length are anagrams
    new_lst_char_poss_str = []

    for i in lst_char_poss_str:
        i = list(i)#sorted list, so, "abb" and "bba" will be both "abb"
        i.sort()
        new_lst_char_poss_str.append(i)#a 2-d list of lists of characters for All possible substrings within string

    len_new_s = len(new_lst_char_poss_str)

    for i in range (len_new_s - 1):
        for j in range (i + 1, len_new_s):
            if new_lst_char_poss_str[i] == new_lst_char_poss_str[j]:
                count += 1
                
    return(count)

代码 2:

def sherlockAndAnagrams(s):
    count = 0
    slen = len(s)

    for i in range(slen):
        for j in range(i+1, slen):
            substr = ''.join(sorted(s[i:j]))#Sortingall characters after a char in string
            sublen = len(substr)

            for x in range(i+1, slen):
                if x + sublen > slen: #if index out of range
                    break

                substr2 = ''.join(sorted(s[x:x+sublen]))
                if substr == substr2:
                    anagrams += 1

    return count

【问题讨论】:

  • 似乎在您的代码中lst_char_poss_str(因此new_lst_char_poss_str)的长度为O(n^2),然后您在len(new_lst_char_poss_str) 上执行双循环。那么你的代码不是O(n^4)吗?
  • 这两个双嵌套循环不是按顺序排列的吗?如果后面的双嵌套循环嵌套在前一个双嵌套循环中,我想它可能是 O(n^4) 。不是吗?
  • 重要的不是循环次数,而是迭代次数。最后两个循环中的每一个都有O(n^2) 迭代。
  • 最后一个双嵌套循环在 O(len_new_s ^ 2) 时间内运行。由于第一个双嵌套循环的工作方式,len_new_s 是 O(len_s ^ 2)。这意味着您的代码复杂度为 O(len_s ^ 4)。如果我们选择nlen(s),那么您的代码的复杂度为 O(n ^ 4)。关键是您必须选择n,然后将所有循环限制关联到n。你不能随意使用n 来限制每个循环。
  • 绝对是的,具有更高复杂度的算法在 n 的某个范围内可能更快。例如,introsort 根据正在处理的分区子集的大小在合并排序、快速排序和插入排序之间切换。 GNU 标准库的排序实现使用 introsort 并在 n

标签: python algorithm performance big-o


【解决方案1】:

您可能有一个运行时间为 1,000,000 n 的算法,因为您可能正在执行一些其他操作。但是你可能有这个运行时间的算法。 1,000,000n 是 O (n),因为这是

你会说 1,000,000 n 算法优于 2 n^2。线性运行时间为 O (n) 的运行时间优于 O ( n^2)。这是真的,但在极限内,当 n 真的很大时,极限很晚才达到。对于小型实例,这 2 n^2 实际上可能比您的 1,000,000 n 花费的时间更少。我们还必须注意常量。

【讨论】:

    【解决方案2】:

    有很多要点需要考虑:

    • 第二种算法总是返回0,没有人递增count
    • 第一个:temp_str += s[j] 效率不高,第二个不使用此字符串连接。
    • 第二个更快,因为使用切片来检索字符串片段。但可以肯定的是,也许您必须对代码进行精确的分析。

    除此之外,正如@pjs 所说,大 O 表示法是一种渐近解释。

    【讨论】:

      猜你喜欢
      • 2017-02-08
      • 1970-01-01
      • 2023-03-17
      • 1970-01-01
      • 2017-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多