力扣——1010. 总持续时间可被 60 整除的歌曲
1010. 总持续时间可被 60 整除的歌曲
在歌曲列表中,第 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 * 1041 <= time[i] <= 500
问题解析
做法类似两数之和的哈希表做法。
可以用哈希表记录每个元素的出现次数。
然后我们再次遍历数组,对于每一个数,我们枚举60的倍数,看哈希表内有多少数能和他组成这个60的倍数。比如110,能和10、70组成60的倍数,那就看10和70的出现次数就可以。
然后把所有结果相加。
要注意的地方:
为了防止重复计数,我们只看比当前元素小的其它元素。也就是说我们枚举60的倍数j,则j-time[i]要小于time[i]。比如110虽然也能和130组合成60的倍数,但我们只要小于110的,也就是只计算10和70的出现次数
也是为了防止重复计数,当出现j-time[i]=time[i]的情况时,我们从哈希表内取数的方式要改变。
或者为了方便,直接对数组排序,再一边枚举60的倍数,一边记录元素的出现次数。
AC代码
class Solution {
public:
int numPairsDivisibleBy60(vector<int>& time) {
unordered_map<int,int>mymap;
sort(time.begin(),time.end());
int ans=0;
for(auto&i:time)
{
for(int j=60;j<=1000;j+=60)
{
if(j-i>i)break;
ans+=mymap[j-i];
}
mymap[i]++;
}
return ans;
}
};