我正在尝试解决来自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
答案 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)