Leetcode 1013:总持续时间可被 60 整除的歌曲(超详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[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. 1 <= time.length <= 60000
  2. 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:

https://leetcode.com/problems/pairs-of-songs-with-total-durations-divisible-by-60/discuss/256738/JavaC%2B%2BPython-Two-Sum-with-K-60

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/88633878