我的代码的哪一部分导致“超时错误”,为什么?

时间:2019-12-18 06:42:04

标签: python python-3.x algorithm

我正在尝试在Hackerrank:https://www.hackerrank.com/challenges/climbing-the-leaderboard上解决此问题。问题陈述基本上指出,爱丽丝一个人和另一个爱丽丝有两组分数,当与其他玩家的得分相比时,我们必须使用dense ranking并显示爱丽丝的排名。在大型测试案例中,这给了我超时错误。我已经在Hackerrank上使用了论坛建议,并获得了成功,但是我特别想知道代码中的问题。这是我的代码:

class Dict(dict):

    def __init__(self):
        self=dict()

    def add(self,key,value):
        self[key]=value

def climbingLeaderboard(scores, alice):

    alice_rank=[]
    for i in range(len(alice)):
        scores.append(alice[i])
        a=list(set(scores))
        a.sort(reverse=True)
        obj=Dict()
        b=1
        for j in a:
            obj.add(j,b)
            b+=1
        if alice[i] in obj:
            alice_rank.append(obj[alice[i]])
    scores.remove(alice[i])        
    return alice_rank

2 个答案:

答案 0 :(得分:3)

您的代码中有几个问题,但最重要的是以下问题。

...
scores.append(alice[i])
a=list(set(scores))
a.sort(reverse=True)
...

在每次迭代中,您都将Alice的得分添加到scores,然后对scores进行排序。这里的成本已经是O(nlog(n)),其中n-scores中的元素数。因此,您的总时间复杂度变为O(n*n*log(n))。这太多了,因为n可以达到200000,因此对于您的解决方案而言,最多可以进行200000*200000*log(200000)个操作。

当然,还有另一个问题:

...
for j in a:
    obj.add(j,b)
    b+=1
...

但是,由于循环时间的复杂度为O(n),因此它还没有上一个版本差。

存在一个O(n*log(n))时间复杂度解决方案。我会给您一个总体思路,以便您可以轻松地自己实现。

  • 如果您记得得分重复的玩家在排行榜上的位置相同,则可以在循环之前将scores转换为一个没有重复的数组,例如list(set(scores))。在这种情况下,第一个位置对应最高得分,第二个位置对应第二最高得分,依此类推(每个问题陈述的初始数组按降序排列)。
  • 基于上述步骤,对于每个score的爱丽丝,您都可以在数组中找到一个位置,使玩家的得分小于或等于score。由于数组已排序,因此查找将花费O(log(n))。例如,如果玩家的分数为40, 30, 10,而爱丽丝的分数为35,则找到的位置将为2(对于算法描述,我认为第一个索引从{ {1}}),因为1占据该位置,该位置是爱丽丝在排行榜中的 ACTUAL 位置,因此可以立即打印。
  • 另一个技巧-您可以使用bisect模块在​​数组中执行二进制搜索。

因此,建议的解决方案的总体时间复杂度为30。它将通过所有测试用例(我已经尝试过)。

答案 1 :(得分:1)

执行重复排序(a.sort(reverse = True))会花费大量时间。我有同样的问题。如果您阅读了该问题,您会发现分数是按顺序输入的(升序或降序)。 诀窍是利用这种固有的输入顺序。

还有一件事,由于嵌套循环,您的代码的时间复杂度为O(n ^ 2),而您所讨论的论坛可能是使用O(n)(不确定)进行的。