版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/88633878
在歌曲列表中,第 i
首歌曲的持续时间为 time[i]
秒。
返回其总持续时间(以秒为单位)可被 60
整除的歌曲对的数量。形式上,我们希望索引的数字 i < j
且有 (time[i] + time[j]) % 60 == 0
。
示例 1:
输入:[30,20,150,100,40]
输出:3
解释:这三对的总持续时间可被 60 整数:
(time[0] = 30, time[2] = 150): 总持续时间 180
(time[1] = 20, time[3] = 100): 总持续时间 120
(time[1] = 20, time[4] = 40): 总持续时间 60
示例 2:
输入:[60,60,60]
输出:3
解释:所有三对的总持续时间都是 120,可以被 60 整数。
提示:
1 <= time.length <= 60000
1 <= time[i] <= 500
解题思路
我首先看到的数据是60000
,所以我们不能通过暴力解决,但是比赛的时候,同学使用java
过了,但是使用python
过不了。
这个问题和之前的问题Leetcode 1:两数之和(最详细解决方案!!!)非常类似,我们观察到tims[i]
的最大值是500
,我们可以计算出最大倍数1000//60=16
。所以我们可以遍历time
,然后将对应元素添加到dict
中。然后判断(i*60 - t)
(其中)是不是遍历过,然后遍历过的话,我们就需要将其出现次数添加到res
中,最后返回res
。
from collections import defaultdict
class Solution:
def numPairsDivisibleBy60(self, time: List[int]) -> int:
seen = defaultdict(int)
res = 0
for t in time:
for i in range(1, 17):
lat = i*60
if lat > t and (lat - t) in seen:
res += seen[lat-t]
seen[t] += 1
return res
还有一种更好的做法,我们可以将所有的time
进行time%60
,这样我们数的区间就变成了[0,60]
,这样的话我们就不用遍历[1,17]
了,彻底将这个问题变成了两数和问题。
from collections import Counter
class Solution:
def numPairsDivisibleBy60(self, time: List[int]) -> int:
cnt = Counter()
res = 0
for t in time:
res += cnt[-t % 60]#trick
cnt[t % 60] += 1
return res
上面写法使用了trick
,更明确的表述应该是cnt[(60-t%60)%60]
(为何不是cnt[(60-t%60)]
?例如t=180
,显然我们需要的区间在[0,59]
)。
reference:
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!