hackerrank“制作字谜”挑战超时失败

Posted

技术标签:

【中文标题】hackerrank“制作字谜”挑战超时失败【英文标题】:Timeout failure on hackerrank "Making Anagram" challenge 【发布时间】:2018-03-16 05:06:54 【问题描述】:

堆栈上的第一个问题, 我在hackerrank的前几个挑战中遇到了“多少删除来分析2个单词”。我在网上看到了其他一些解决方案,但我不明白为什么我的速度慢得多。我似乎有一个“正确”的算法,因为我计算了一些测试用例并找到了相应的预期输出

def number_needed(a, b):
    count = 0
    isFound = False
    matchedBs = []

    for letterA in a:
        for j,letterB in enumerate(b):
            if letterA == letterB and (j not in matchedBs):
                isFound = True
                matchedBs.append(j)
                break
        if not isFound:
            count += 1
        isFound = False

    return count + (len(b)-len(matchedBs))      

a = input().strip()
b = input().strip()
print(number_needed(a, b))

所以我想弄清楚我的算法的总体思路是瓶颈还是其中的一些错误。 谢谢!

【问题讨论】:

每个字母是否只出现一次?因为matchedBs每个字母只有一次。 @BradSolomon 失败的测试用例使用 400-500 个字符字符串 @inarilo 没有一个字母可以出现多次,但我不确定为什么会出现问题。 我不知道python所以也许我弄错了,但你似乎忽略了任何已经在matchedBs中的字母,所以任何重复的字母都不会被计算在内,你似乎也不会检查重复的字母是否匹配 B 中的重复字母,而不是已经匹配的相同出现.. if 语句的第二部分检查是否存在? "letterA == letterB and (j not in mappedBs)" 【参考方案1】:

你可以在这里使用line profiling。你可以使用conda install line_profiler

首先将您的函数合并到一个脚本中,并用@profile 装饰它。这是那个脚本:

# number_needed.py

from string import ascii_letters
import numpy as np

@profile
def number_needed(a, b):
    count = 0
    isFound = False
    matchedBs = []

    for letterA in a:
        for j,letterB in enumerate(b):
            if letterA == letterB and (j not in matchedBs):
                isFound = True
                matchedBs.append(j)
                break
        if not isFound:
            count += 1
        isFound = False

    return count + (len(b)-len(matchedBs))

np.random.seed(123)
s1 = ''.join(np.random.choice(list(ascii_letters), size=500).tolist())
s2 = ''.join(np.random.choice(list(ascii_letters), size=500).tolist())

def main():
    return number_needed(s1, s2)

if __name__ == '__main__':
    main()

然后在 IPython/JupyterQt 中调用下面的命令。您可能需要根据您所在目录的外观更改路径:

%run C:/Users/YOURNAME/Anaconda3/pkgs/line_profiler-2.0-py36_0/Lib/site-packages/kernprof.py -l -v number_needed.py

结果会逐行显示一些有用的统计信息。

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     5                                           @profile
     6                                           def number_needed(a, b):
     7         1            5      5.0      0.0      count = 0
     8         1            3      3.0      0.0      isFound = False
     9         1            2      2.0      0.0      matchedBs = []
    10                                           
    11       501          468      0.9      0.2      for letterA in a:
    12    136321       133965      1.0     46.4          for j,letterB in enumerate(b):
    13    136229       151929      1.1     52.6              if letterA == letterB and (j not in matchedBs):
    14       408          371      0.9      0.1                  isFound = True
    15       408          585      1.4      0.2                  matchedBs.append(j)
    16       408          425      1.0      0.1                  break
    17       500          472      0.9      0.2          if not isFound:
    18        92          105      1.1      0.0              count += 1
    19       500          459      0.9      0.2          isFound = False
    20                                           
    21         1            5      5.0      0.0      return count + (len(b)-len(matchedBs))

看起来for j,letterB in enumerate(b): 被嵌套是你的罪魁祸首。您正在评估 136,000 次以下的行。也就是说,您在循环中运行的操作每次点击所花费的时间一样长,但它们几乎从未被评估过,因此作为一个整体,它们不会占用您的时间。 p>

不过,运行时似乎还不错。 s1s2 在我的机器上为 14.7 毫秒。

【讨论】:

【参考方案2】:

您的代码具有 O(n3) 复杂度(n 是 ab 的长度):您循环 a 中的每个字符,将它们与 @987654325 中的每个字符进行比较@,然后检查该索引是否在已经匹配的字符列表中,这也是线性复杂度。

作为一种快速修复,您可以将matchedBs 设为set,从而将复杂度降低到 O(n²)。但你可以做得更好:只需计算 ab 中的所有单个字符。不要为此使用str.count,否则您将再次获得O(n²);相反,使用dict 将字符映射到它们的计数,循环ab 一次,并相应地更新这些计数。最后,只需将 ab 的计数差相加即可。

或者,使用 Python 的库,您可以为 ab 创建两个 collections.Counter 并进行比较。

【讨论】:

以上是关于hackerrank“制作字谜”挑战超时失败的主要内容,如果未能解决你的问题,请参考以下文章

在hackerrank中因超时而终止[关闭]

Python Hackerrank挑战给出了〜stdout没有响应〜错误

[不使用TOP的SELECT SSMS的最后一行Hackerrank挑战者

如何优化 Haskell 代码以通过 HackerRanks 超时测试用例(不是为了任何正在进行的比赛,只是我在练习)

用php中的两个单词制作字谜

CTCI 制作字谜 - 得到不正确的输出