Leetcode刷题Python之3185.构成整天的下标对数目II

提示:直接暴力求解会超过执行时间,因此要考虑其他方法降低复杂度。


问题描述

给定一个整数数组 hours,表示时间,以小时为单位。我们需要找到数组中满足 i < j 且 hours[i] + hours[j] 构成整天(即 24 的倍数)的下标对 i 和 j 的数目。整天可以是 1 天(24 小时),2 天(48 小时),以此类推。


一、示例:

示例 1:

输入: hours = [12,12,30,24,24]
输出: 2
解释:构成整天的下标对分别是 (0, 1)(3, 4)
输入: hours = [72,48,24,3]
输出: 3
解释:构成整天的下标对分别是 (0, 1)(0, 2)(1, 2)

二、解题思路

1. 找余数

我们需要找到满足 hours[i] + hours[j] 是 24 的倍数的下标对。首先,观察到对于任意两个数 hours[i] 和 hours[j],如果它们之和是 24 的倍数,那么 hours[i] % 24 + hours[j] % 24 = 24 或者 hours[i] % 24 + hours[j] % 24 = 0。

因此,可以将每个数对 24 取模,得到一个余数,然后我们只需要找到两个余数之和为 24 的数对,或者两个余数都是 0。

2. 利用哈希表存储余数

为了加快查找配对余数的速度,我们可以使用一个大小为 24 的数组 count 来存储余数出现的频率。通过遍历数组 hours,我们可以计算每个元素对 24 的余数,并存储这些余数出现的次数。

当我们处理到某个 hour 时:

如果 hour % 24 == 0,则表示它可以和之前所有余数为 0 的元素配对。
如果 hour % 24 != 0,则需要寻找数组中是否存在 24 - remainder 这样的余数,它们相加就能构成 24 的倍数。

3. 逐步统计配对数

每次找到一对满足条件的余数时,记录它们的配对次数。最终,返回所有配对的总数即可。

代码实现

class Solution(object):
    def countCompleteDayPairs(self, hours):
        """
        :type hours: List[int]
        :rtype: int
        """
        count = [0] * 24  # 用一个大小为24的数组存储余数的频率
        pairs = 0        
        for hour in hours:
            remainder = hour % 24  # 计算余数
            if remainder == 0:
                # 余数为0的数可以和之前所有余数为0的数配对
                pairs += count[0]
            else:
                # 查找是否存在能够配对的余数
                pairs += count[24 - remainder]
            
            # 更新余数频率
            count[remainder] += 1      
        return pairs

解释代码

1,初始化 count 数组: 我们使用一个大小为 24 的数组 count 来记录每个余数出现的次数。数组索引代表余数,数组的值代表该余数出现的次数。

2,遍历 hours 数组: 对于数组中的每个 hour,我们计算 remainder = hour % 24。
如果余数 remainder == 0,说明这个数可以和之前所有余数为 0 的数配对。于是将 count[0] 加入 pairs 中。如果 remainder != 0,我们需要找是否有 24 - remainder 的余数存在。如果存在,这些余数能够和当前的 hour 配对,所以我们将 count[24 - remainder] 加入 pairs 中。

3,更新频率数组: 无论当前的 remainder 是什么,我们都会将它在 count 数组中的计数加 1,表示这个余数的出现次数。

复杂度分析

时间复杂度: O(n),因为我们只需遍历一次数组,每个元素的余数计算和查找都是 O(1) 操作。
空间复杂度: O(1),因为我们使用了一个固定大小为 24 的数组 count,不依赖于输入数据的大小。
相比使用哈希表存储余数频率,这里我们直接使用数组,因为余数范围固定为 0 到 23,所以数组能够在 O(1) 时间内完成查找和更新,进一步提高了效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值