LeetCode/总持续时间可被 60 整除的歌曲

发布时间 2023-05-07 01:33:04作者: 失控D大白兔

在歌曲列表中,第 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;
    }
};