降低Python3中HackerRank排序问题的时间复杂度

时间:2018-12-28 07:37:23

标签: python python-3.x sorting median

我正在尝试解决来自HackerRank的Python3排序问题:https://www.hackerrank.com/challenges/fraudulent-activity-notifications/problem

此问题需要找到运行中的每个子列表的中位数。

我的代码通过了示例测试用例,但由于超时终止而未完全通过实际的测试用例。我怀疑每次使用sort()来查找中位数都会导致时间滞后。

如何改善代码?

def activityNotifications(expenditure, d):
    totalDays = len(expenditure)
    notified = 0

    for x in range(d, totalDays):
        check = expenditure[x-d:x]
        check.sort()

        if d % 2 == 0:
            median = (check[int(d/2)] + check[int((d-2)/2)])/2
        else:
            median = check[int((d-1)/2)]

        if expenditure[x] >= median * 2:
            notified += 1

    return notified

1 个答案:

答案 0 :(得分:2)

要在每次迭代中找到中值,请对子数组进行排序。这不是真正有效的方法,尤其是在d不小的情况下。每次迭代的时间复杂度为O(dlog(d))

要找到中位数,我们需要一个排序数组,但不需要sort()方法。如果我们注意到每个expenditure[i]都在[0;200]范围内,那么这里的计数排序听起来是个好主意。基本上,我们使用i计算每个数字counts[i]的频率。要获得排序数组,我们只需要迭代j: counts[j] > 0

因此,如果counts在每个长度expenditure(间隔d)的每个间隔内保持[i; i + d)个数字的频率,我们最多可以通过检查{{1 }}个来自201的数字(有关详细信息,请参见代码)。移至下一个间隔counts,需要将数字[i+1; i+d+1)的频率递减为i,并递增数字counts[i]--。 这种方法需要i+d的时间和O(n*201)的空间复杂度。

现在,请参见下面的代码:

O(201)