LeetCode/总持续时间可被 60 整除的歌曲
在歌曲列表中,第 i 首歌曲的持续时间为 time[i] 秒
返回其总持续时间(以秒为单位)可被 60 整除的歌曲对的数量
1. 打表(数据量较小)
列出60的倍数+哈希查找
class Solution {
public:
int numPairsDivisibleBy60(vector<int>& time) {
int n = time.size();
long count = 0;
map<int,int> m;
for(int i =0;i<n;i++)
m[time[i]]++;
int cur = 0;
vector<int> nums;
for(int i=0;i<20;i++){
cur+=60;
nums.push_back(cur);
}
for(auto it = m.begin();it!=m.end();it++){//从小到大遍历
auto index = lower_bound(nums.begin(),nums.end(),it->first);//找第一个大于等于的值
while(index!=nums.end()){
int sub = *index - it->first;
if(sub==it->first) count += calculate(it->second-1)*2;
else if(m.count(sub)) count += it->second*m[sub];
index++;
}
}
return count/2;
}
long calculate(int n){
long res = 0;
while(n!=0){
res+=n;
n--;
}
return res;
}
};
2. 预先取模
先对所有数据取模减少计算量
class Solution {
public:
int numPairsDivisibleBy60(vector<int>& time) {
int n = time.size();
int count = 0;
map<int,int> m;
for(int i =0;i<n;i++){
time[i] = time[i]%60;
m[time[i]]++;
}
for(auto it = m.begin();it!=m.end()&&it->first<=30;it++){//从小到大遍历
int sub = 60 - it->first;
if(it->first==30||it->first==0) count += calculate(it->second-1);
else if(m.count(sub)) count += it->second*m[sub];
}
return count;
}
long calculate(int n){
return (long)(1+n)*n/2;
}
};
优化写法(数组作哈希表)
class Solution {
public:
int numPairsDivisibleBy60(vector<int>& time) {
vector<int> cnt(60);
for (int t : time)
cnt[t % 60]++;
long long res = 0;
for (int i = 1; i < 30; i++)
res += cnt[i] * cnt[60 - i];
res += (long long)cnt[0] * (cnt[0] - 1) / 2 + (long long)cnt[30] * (cnt[30] - 1) / 2;
return (int)res;
}
};