当前位置: 首页 > article >正文

【力扣每日一题】解答分析 1010. 总持续时间可被 60 整除的歌曲对数

1010. 总持续时间可被 60 整除的歌曲对数

题目简介

给定一个整数数组 time,表示每首歌曲的持续时间(以秒为单位),我们希望计算出数组中所有歌曲对 (i, j),使得 i < j 且满足 (time[i] + time[j]) % 60 == 0。换句话说,找出所有的歌曲对,使得它们的播放时间之和能够被 60 整除。

题目要求

  • 找出所有歌曲对 (i, j),使得它们的播放时间之和被 60 整除。
  • 解决方案应该能处理 time.length 最大为 6 * 10^4 的情况,因此我们需要优化暴力算法。

暴力解法

暴力解法是直接遍历所有可能的 (i, j) 对,检查它们的总持续时间是否能被 60 整除。虽然这种方法直观且简单,但它的时间复杂度是 O(n^2),在数据量较大的情况下会超时,无法满足题目对时间效率的要求。

暴力解法代码
class Solution:
    def numPairsDivisibleBy60(self, time: List[int]) -> int:
        res = 0
        n = len(time)
        for i in range(n):
            for j in range(i + 1, n):
                if (time[i] + time[j]) % 60 == 0:
                    res += 1
        return res

问题与瓶颈

  • 由于暴力解法需要两层循环来遍历所有可能的 (i, j) 对,时间复杂度为 O(n^2),对于输入大小达到 6 * 10^4 时,可能导致超时。

  • 对于 n 较大的输入,暴力算法会执行大约 ( \left(6 \times 10^4 \right)^2 ) 次运算,显然不符合时间要求。

优化思路

我们可以通过 余数配对 的方式来优化该算法,使用一个大小为 60 的数组来统计每个余数出现的次数。具体优化过程如下:

1. 利用余数的特性

对于任意一对歌曲,假设它们的播放时间分别为 t1t2。我们希望 t1 + t2 能被 60 整除,即 (t1 + t2) % 60 == 0。这意味着:

  • 如果 t1 % 60 = r1,那么 t2 % 60 = (60 - r1) % 60,才能使得两者的和能被 60 整除。

  • 因此,我们可以通过记录每个余数出现的次数,快速找到哪些余数的组合能使得和为 60 的倍数。

2. 优化步骤

  • 遍历 time 数组中的每个元素,计算其余数 t % 60
  • 对于每个余数 t % 60 = r,我们要找到与其配对的余数 (60 - r) % 60,并累加已经出现过的配对次数。
  • 使用一个大小为 60 的数组 yu_count 来记录每个余数的出现次数。

这样,算法的时间复杂度就降低为 O(n),大大提高了效率。

优化后的代码
class Solution:
    def numPairsDivisibleBy60(self, time: List[int]) -> int:
        yu_count = [0] * 60  # 用来记录余数出现的次数
        res = 0
        
        for x in time:
            t = x % 60  # 计算当前时间的余数
            target = 60 - t if t != 0 else 0  # 计算与当前余数 t 配对的余数
            res += yu_count[target]  # 如果存在这样的余数,累加配对数量
            yu_count[t] += 1  # 更新当前余数的出现次数
        
        return res

代码解释

  1. yu_count 数组

    • yu_count[i] 表示余数为 i 的歌曲出现的次数。该数组的大小为 60,因为余数的范围是 0 到 59。
  2. 遍历 time 数组

    • 对于每个歌曲的播放时间 x,计算它的余数 t = x % 60
    • 然后找出需要与当前余数配对的目标余数 target = 60 - t(对于 t == 0,目标余数是 0),并累加已经出现的配对数量。
    • 更新当前余数 t 的出现次数。

时间复杂度和空间复杂度

  • 时间复杂度O(n),其中 n 是歌曲数。我们只遍历一遍 time 数组,每次更新和查询都是常数时间操作。

  • 空间复杂度O(1),因为 yu_count 数组的大小是固定的 60。

测试案例

示例 1:

输入:

time = [30, 20, 150, 100, 40]

输出:

3

解释:

  • (30 + 150) % 60 == 0
  • (20 + 40) % 60 == 0
  • (100 + 20) % 60 == 0

示例 2:

输入:

time = [60, 60, 60]

输出:

3

解释:

  • (60 + 60) % 60 == 0
  • (60 + 60) % 60 == 0
  • (60 + 60) % 60 == 0

示例 3:

输入:

time = [10, 50, 20, 40, 30]

输出:

3

解释:

  • (10 + 50) % 60 == 0
  • (20 + 40) % 60 == 0
  • (30 + 30) % 60 == 0

错误与改进对比

错误的暴力解法:

暴力解法的时间复杂度是 O(n^2),对于 n 较大的情况下,可能会导致超时错误,尤其当 n 接近 6 * 10^4 时。

优化后的解法:

优化后的解法通过哈希表统计余数的出现次数,将时间复杂度降低到 O(n),并且能够在题目给定的时间限制内正确处理大规模数据。

总结

  • 通过优化余数的配对计算,利用哈希表存储余数出现次数,将暴力解法的时间复杂度从 O(n^2) 降低到了 O(n)
  • 优化后的解法不仅简洁高效,还能处理大规模数据输入,符合题目的性能要求。

http://www.kler.cn/a/524077.html

相关文章:

  • PostgreSQL 约束
  • 51单片机开发:定时器中断
  • 如何获取小程序的code在uniapp开发中
  • [权限提升] Windows 提权 — 系统内核溢出漏洞提权
  • 2025-01-28 - 通用人工智能技术 - RAG - 本地安装 DeepSeek-R1对话系统 - 流雨声
  • ubuntu取消输入密码
  • MySQL深度解析与优化实践
  • 【问题】Chrome安装不受支持的扩展 解决方案
  • 【数组OJ】两数之和
  • 28. C语言 递归:深入理解与高效应用
  • 【Linux】 冯诺依曼体系与计算机系统架构全解
  • DeepSeek是由杭州深度求索人工智能基础技术研究有限公司(简称“深度求索”)发布的一系列人工智能模型
  • linux学习之网络编程
  • 51c深度学习~合集3
  • R语言统计分析——ggplot2绘图2——几何函数
  • 单向循环链表的概念+单向循环链表的结点插入+单向循环链表的结点删除+程序设计与笔试题分析
  • 构建可靠的时间序列预测模型:数据泄露检测、前瞻性偏差消除与因果关系验证
  • Kafka 深入客户端 — 分区分配策略与协调器
  • Luzmo 专为SaaS公司设计的嵌入式数据分析平台
  • 【Validator】字段验证器struct与多层级验证,go案例
  • ReentrantLock锁江湖:一柄寒刃镇并发纷争
  • ts 基础核心
  • 2025-01-28 - 通用人工智能技术 - RAG - 本地安装 DeepSeek-R1对话系统 - 流雨声
  • 拟合损失函数
  • C语言练习(29)
  • PWM频率测量方法