本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、题目描述:
1010. 总持续时间可被 60 整除的歌曲 - 力扣(LeetCode) (leetcode-cn.com)
在歌曲列表中,第 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 * 10^4
- 1 <= time[i] <= 500
二、思路分析:
题中形式上,希望索引的数字 i 和 j 满足 i < j 且有 (time[i] + time[j]) % 60 == 0。
所以我们可以变换着思考解题,由于要求可以被60整除,可以把数字变换一下再进行计算
如下:
[30,20,150,100,40] = [30,20,30,40,40],余上60后,我们就比较容易进行查找了。
这里没有按顺序查找,而是使用类似hash表的形式;如下:
- 首先统计每个数字的个数,20->1个,30->2个,40->2个;
- 依次匹配就可以了,对于20我们找40,对于30我们找30;需要注意,题中要求从左向右(i<j),所以当30=30时,我们对数的累加为1+2+3+...+cnt-1;其它的则为cnt1*cnt2;
三、AC 代码:
#define MAXS 60
int numPairsDivisibleBy60(int* time, int timeSize) {
int pTime[MAXS] = { 0 };
int i = 0;
while (i < timeSize) {
time[i] = time[i] % 60;
pTime[time[i]]++;
i++;
}
int resCnt;
i = resCnt = 0;
int visit[MAXS] = { 0 };
while (i < MAXS) {
if (pTime[i] != 0 && visit[i] == 0) {
int base = i;
int res = (60 - base) % 60;
if (pTime[res] != 0) {
if (res == base) {
for (int j = 1; j < pTime[base]; j++) {
resCnt += j;
}
} else {
resCnt += pTime[base] * pTime[res];
}
visit[res] = 1;
}
visit[i] = 1;
}
i++;
}
return resCnt;
}
范文参考:
1010. c++几乎双百的哈希解法 - 总持续时间可被 60 整除的歌曲 - 力扣(LeetCode) (leetcode-cn.com)