「这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战」
说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)
作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
题意描述
在歌曲列表中,第 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
分析
当我们看到数据集小于等于60000即为1e5左右,所以时间复杂度在你n^2的基本上都不考虑。 那怎么来解决时间的问题呢,我们来分析分析题目。首先保存有限个整数类型时,可以考虑用数组的索引来代表。
- 但是如果只是用数组存储这些整形的话,想得到某个值时都需要遍历整个数组。很容易造成O(n^2)
- 但是如果用数组索引来存储的话,通过下标获取的时间是O(1)的。
而我们要求的是余数之和等于**60的pair。**即余数之和等于60意味着他们的和可以被60整除。有一个特殊情况要考虑,那就是我们找到的数已经被60整除了,这种情况我们需要特判一下。
var numPairsDivisibleBy60 = function(time) {
let yushu=new Array(61).fill(0);
let res=0,thir=0;
for(let i in time)
{
yushu[time[i]%60]++;
}
for(let j=0;j<=30;j++)//循环控制重复
{
if(j==30||j==0)//和自己排列组合,减去和自身配对结果重复配对,所以再除以2
thir=thir+(yushu[j]*yushu[j]-yushu[j])/2;
else//简单排列组合,不担心序号相同
res=res+yushu[j]*yushu[60-j];
}
res=res+thir;
return res;
};
还有一种方式,其实我们可以通过数学推算出来一个公式。n * (n - 1) / 2
var numPairsDivisibleBy60 = function(time) {
let sum = 0;
let arr = Array(60).fill(0);
for(let i = 0; i < time.length; i++) {
arr[time[i]%60] += 1;
}
sum += arr[0] * (arr[0] - 1) / 2;
sum += arr[30] * (arr[30] - 1) / 2;
let l = 1, r = 59;
while(l < r){
sum += arr[l++] * arr[r--];
}
return sum;
};
感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。
写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤