在问 · 算法题解

1010. 总持续时间可被 60 整除的歌曲

题目描述

输入数组 time,time[i] 是第 i 首歌的时长,单位为秒。

统计满足 i < j 且 (time[i] + time[j]) % 60 == 0 的下标对 (i, j) 的个数,返回这个数。

示例 1
输入:time = [30,20,150,100,40]
输出:3

解释:满足条件的是 30+150、20+100、20+40 这三对。

示例 2
输入:time = [60,60,60]
输出:3

解释:任意两首相加都是 120,三首歌两两配对共 3 对。

数据范围

  • 1 <= time.length <= 6 * 10^4
  • 1 <= time[i] <= 500

解题思路

两数之和能被 60 整除,只看它们除以 60 的余数:余数 r 需要配余数 (60 - r) % 60。用长度 60 的计数数组当哈希表,从左到右扫描:每首歌先把前面配对余数的个数加到答案,再把自己的余数计数加一。和“两数之和”一样,只是把“等于”换成了“同余”。

为什么正确

处理到第 j 首歌前,cnt[r] 是前 j 首中余数为 r 的歌曲数,ans 是两首都在前 j 首中的合法对数。

复杂度分析

时间 O(n),空间 O(60) = O(1)。

易错点

余数为 0 的歌曲要和余数 0 配对,直接写 60 - r 会得到下标 60 越界,所以要再模 60。余数 30 与自己配对,必须先累加再计数,否则一首歌会和自己组成一对。答案可达 n^2/2 约 1.8×10^9,C++/Java 里用 64 位累加更稳妥。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def numPairsDivisibleBy60(self, time: List[int]) -> int:
        cnt = [0] * 60
        ans = 0
        for t in time:
            r = t % 60
            ans += cnt[(60 - r) % 60]
            cnt[r] += 1
        return ans

载入编辑器,自己跑一遍 →

哈希表 专题的其他题目

查看 哈希表 全部题目 →