LeetCode.1010.总持续时间可被60整除的歌曲(c语言)
链接: link
题目
在歌曲列表中,第 i 首歌曲的持续时间为 time[i] 秒。
返回其总持续时间(以秒为单位)可被 60 整除的歌曲对的数量。形式上,我们希望索引的数字 i 和 j 满足 i < j 且有 (time[i] + time[j]) % 60 == 0。
示例 1:
输入:[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:
输入:[60,60,60]
输出:3
解释:所有三对的总持续时间都是 120,可以被 60 整数。
提示:
1 <= time.length <= 60000
1 <= time[i] <= 500
思路(巧用数组解法):
1.建立数组nums[60]:
提示中说time.length在[1,60000]之间,time[i]在[1,500]之间,且这是一个求余数的题目,那么30和150的作用是一样的,因为它们除60的余数都是30,根据这个思路,建立一个nums[60]数组,数组下标表示某一首歌曲的时间除以60的余数,nums[i]的值表示余数为i的歌曲数目有多少,这样就将一个非常大的数组简化成一个大小为60的数组。示例1中:[30,20,150,100,40]中对应的nums[]为nums[20] = 1,nums[30] = 2,nums[40] = 2;
2.研究数组:
特例:歌曲的time除60余数结果为0或者30的情况,如示例2中:[60,60,60]对应nums[]为:nums[0] = 3;此时最终count为3(所有三对的总持续时间都是 120,可以被 60 整数);
如果是[60,60,60,60]时,对应nums[]为:nums[0] = 4;此时count为6,如此递推得到关系式:count += num[i] * (nums[i] - 1) / 2,(i只可以是0或者30)。
一般情况:当i为1-29时,只要找到nums[i]和nums[60-i]的值进行相乘即可,如示例1中,nums[20] = 1 ;nums[40] = 2;此时count=1*2=2;得到一般式:count += nums[i] * nums[60 - i]
代码:
int numPairsDivisibleBy60(int* time, int timeSize){
int count = 0,i;
int nums[60] = {0};
for(i = 0 ; i < timeSize ; i++)
{
time[i] %= 60;
nums[time[i]]++;
}
for(i = 0 ; i <= 30 ; i++)
{
if(i == 0 || i == 30)
count += nums[i] * (nums[i] - 1) / 2;
else
count += nums[i] * nums[60 - i];
}
return count;
}
结果显示通过。
第一次写这种,虽然最终能通过,但时间复杂度上仍然有进步空间,希望各位看官手下留情,轻点喷,拜了个拜。