原始题目链接:
402场周赛
给你一个整数数组 hours,表示以 小时 为单位的时间,返回一个整数,表示满足 i < j 且 hours[i] + hours[j] 构成 整天 的下标对 i, j 的数目。
整天 定义为时间持续时间是 24 小时的 整数倍 。
例如,1 天是 24 小时,2 天是 48 小时,3 天是 72 小时,以此类推。
示例 1:
输入: hours = [12,12,30,24,24]
输出: 2
解释:
构成整天的下标对分别是 (0, 1) 和 (3, 4)。
示例 2:
输入: hours = [72,48,24,3]
输出: 3
解释:
构成整天的下标对分别是 (0, 1)、(0, 2) 和 (1, 2)。
提示:
1 <= hours.length <= 5 * 105
1 <= hours[i] <= 109
最简单的解题思路:
function countPairs(hours) {
let count = 0; // 用于记录满足条件的下标对数量
for (let i = 0; i < hours.length; i++) {
for (let j = i + 1; j < hours.length; j++) {
if ((hours[i] + hours[j]) % 24 === 0) { // 如果两数之和能被 24 整除
count++; // 计数器加 1
}
}
}
return count; // 返回满足条件的下标对数量
}
let hours1 = [12, 12, 30, 24, 24];
console.log(countPairs(hours1)); // 输出 2
let hours2 = [72, 48, 24, 3];
console.log(countPairs(hours2)); // 输出 3
但这样的时间复杂度较高
解题思路:
function countPairs(hours) {
let count = 0; // 用于记录满足条件的下标对数量
let countMap = {}; // 存储每个余数出现的次数
for (let hour of hours) {
let remainder = hour % 24; // 计算余数
let complement = remainder === 0? 0 : 24 - remainder; // 计算互补的余数
if (countMap[complement]) {
count += countMap[complement]; // 累加互补余数的出现次数
}
if (countMap[remainder]) {
countMap[remainder]++;
} else {
countMap[remainder] = 1;
}
}
return count;
}
本质上,我们通过countMap这个对象,来存储每个余数出现的次数,从而减少方法一里面的两层遍历,使得只用一次遍历即可。