1010. 总持续时间可被 60 整除的歌曲
难度:中等
时间:2023/05/08
在歌曲列表中,第 i 首歌曲的持续时间为 time[i] 秒。
返回其总持续时间(以秒为单位)可被 60 整除的歌曲对的数量。形式上,我们希望下标数字 i 和 j 满足 i < j 且有 (time[i] + time[j]) % 60 == 0。
示例 1:
输入:time = [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:
输入:time = [60,60,60]
输出:3
解释:所有三对的总持续时间都是 120,可以被 60 整除。
提示:
1 <= time.length <= 6 * 10^41 <= time[i] <= 500
解题思路:
首先,对所有时间求 mod 60 的余数,然后进行归类计数,余数相同的为一类。 然后,成对的时间必定 mod 60 的余数之和为 60,比如:余数 20 和 40 的时间数量为 a 和 b,他们之间的配对结果就是 a * b。 特别注意:特殊余数是 0 或 30 的时候,此时必定只和自身类别中的时间进行配对。
实际我们可以把余数桶认为是一个等待配对的“登记表”,每一次得到一个时间值我们都按照如下操作进行处理:
假设之前的“登记表”上的已有的配对都已经被正确处理了,待处理的只有这个新的时间值 检查“登记表”中是否有需要它进行配对的值,有多少个就又增加了多少个配对 本次配对完成,把当前时间值登记入表,等待后面的时间和它进行配对 本解法当然不会分别记录每个新加入的时间对应的配对数量,但是每次处理新的时间会更新结果计数,实际就是递推状态的记录,实际仍然隐含了递推的想法。只要确定了最初没有处理时间时的配对数量作初始值,即可开始从头递推,显然初始值是 0。
class Solution:
def numPairsDivisibleBy60(self, time: List[int]) -> int:
arr = [0] * 60
for t in time:
arr[t % 60] += 1
ans = (arr[0] * (arr[0] - 1) + arr[30] * (arr[30] - 1)) // 2
for i in range(1, 30):
ans += arr[i] * arr[60 - i]
return ans