你完成的完整对局数

标签: 数学 字符串

难度: Medium

一款新的在线电子游戏在近期发布,在该电子游戏中,以 刻钟 为周期规划若干时长为 15 分钟 的游戏对局。这意味着,在 HH:00HH:15HH:30HH:45 ,将会开始一个新的对局,其中 HH 用一个从 0023 的整数表示。游戏中使用 24 小时制的时钟 ,所以一天中最早的时间是 00:00 ,最晚的时间是 23:59

给你两个字符串 startTimefinishTime ,均符合 "HH:MM" 格式,分别表示你 进入退出 游戏的确切时间,请计算在整个游戏会话期间,你完成的 完整对局的对局数

  • 例如,如果 startTime = "05:20"finishTime = "05:59" ,这意味着你仅仅完成从 05:3005:45 这一个完整对局。而你没有完成从 05:1505:30 的完整对局,因为你是在对局开始后进入的游戏;同时,你也没有完成从 05:4506:00 的完整对局,因为你是在对局结束前退出的游戏。

如果 finishTime 早于 startTime ,这表示你玩了个通宵(也就是从 startTime 到午夜,再从午夜到 finishTime)。

假设你是从 startTime 进入游戏,并在 finishTime 退出游戏,请计算并返回你完成的 完整对局的对局数

 

示例 1:

输入:startTime = "12:01", finishTime = "12:44"
输出:1
解释:你完成了从 12:15 到 12:30 的一个完整对局。
你没有完成从 12:00 到 12:15 的完整对局,因为你是在对局开始后的 12:01 进入的游戏。
你没有完成从 12:30 到 12:45 的完整对局,因为你是在对局结束前的 12:44 退出的游戏。

示例 2:

输入:startTime = "20:00", finishTime = "06:00"
输出:40
解释:你完成了从 20:00 到 00:00 的 16 个完整的对局,以及从 00:00 到 06:00 的 24 个完整的对局。
16 + 24 = 40

示例 3:

输入:startTime = "00:00", finishTime = "23:59"
输出:95
解释:除最后一个小时你只完成了 3 个完整对局外,其余每个小时均完成了 4 场完整对局。

 

提示:

  • startTimefinishTime 的格式为 HH:MM
  • 00 <= HH <= 23
  • 00 <= MM <= 59
  • startTimefinishTime 不相等

Submission

运行时间: 22 ms

内存: 16.1 MB

class Solution:
    def numberOfRounds(self, startTime: str, finishTime: str) -> int:
        def get(s: str) -> int:
            return int(s[:2]) * 60 + int(s[3:])

        start, finish = get(startTime), get(finishTime)
        if start > finish:
            finish += 24 * 60
        start, finish = (start + 14) // 15, finish // 15
        return max(0, finish - start)

Explain

首先,将输入时间转换为从当天零点开始计算的分钟数。这样,开始时间和结束时间可以转换为整数,便于计算。如果结束时间小于开始时间,表示玩家玩了一个通宵,因此需要给结束时间加上一天的分钟数(24 * 60)。为了计算完整的对局数,开始时间需要向上取整到最近的一个对局开始时间(即15分钟的倍数),而结束时间需要向下取整。计算这两个时间点之间的完整对局数,即可得到结果。如果计算出来的对局数是负数,则返回0。

时间复杂度: O(1)

空间复杂度: O(1)

class Solution:
    def numberOfRounds(self, startTime: str, finishTime: str) -> int:
        def get(s: str) -> int:
            # 将时间字符串转换为从当天零点开始的分钟数
            return int(s[:2]) * 60 + int(s[3:])

        start, finish = get(startTime), get(finishTime)
        if start > finish:
            # 处理通宵的情况
            finish += 24 * 60
        # 计算对局的起始和结束时间点
        start, finish = (start + 14) // 15, finish // 15
        # 计算完整对局数,确保不返回负数
        return max(0, finish - start)

Explore

在算法中,`start + 14`的用途是确保开始时间向上取整到最近的一个对局开始时间(即15分钟的倍数)。当我们需要将时间向上取整到最近的15分钟倍数时,通常会加上14分钟后再整除15。这是因为整除操作总是取下限(floor),例如:如果开始时间是01分,`1 + 14 = 15`,整除15得到1,即第一个完整的对局从00:15开始。如果开始时间是14分,`14 + 14 = 28`,整除15得到1,下一个对局从00:15开始。这种方法确保了,无论开始时间的分钟数是什么,加14分钟后整除15会正确地向上取整到下一个15分钟的倍数。

使用`(start + 14) // 15`确保开始时间向上取整到下一个15分钟的倍数,而使用`finish // 15`确保结束时间向下取整到最近的15分钟倍数。这样处理后,计算的对局数是两个时间点之间可能进行的最大完整对局数。例如,如果开始时间是00:01,经`(start + 14) // 15`处理后变为00:15;如果结束时间是00:29,经`finish // 15`处理后变为00:15。这种方式确保了只计算开始和结束时间之间完全包含的15分钟对局,从而使得对局数的计算精确。