401. 二进制手表

题目

二进制手表顶部有 4 个 LED 代表 小时(0-11),底部的 6 个 LED 代表 分钟(0-59)。每个 LED 代表一个 0 或 1,最低位在右侧。

  • 例如,下面的二进制手表读取 "4:51" 。

给你一个整数 turnedOn ,表示当前亮着的 LED 的数量,返回二进制手表可以表示的所有可能时间。你可以 按任意顺序 返回答案。

小时不会以零开头:

  • 例如,"01:00" 是无效的时间,正确的写法应该是 "1:00" 。

分钟必须由两位数组成,可能会以零开头:

  • 例如,"10:2" 是无效的时间,正确的写法应该是 "10:02" 。

示例 1:

输入:turnedOn = 1 输出:["0:01","0:02","0:04","0:08","0:16","0:32","1:00","2:00","4:00","8:00"]

示例 2:

输入:turnedOn = 9 输出:[]

提示:

  • 0 <= turnedOn <= 10

解题思路

这道题的本质是:我们需要找到所有的 (hour, minute) 组合,满足以下两个条件:

  1. 取值范围合法:$0 \le hour \le 11$ 且 $0 \le minute \le 59$。
  2. 二进制位合规hour 的二进制中 1 的个数 + minute 的二进制中 1 的个数 == turnedOn

手表的总时间可能性非常有限:小时只有 12 种可能(0-11),分钟只有 60 种可能(0-59)。总共的组合数仅为 $12 \times 60 = 720$ 种。

与其去思考“我有 N 个灯,怎么排列组合放进格子里”,不如直接遍历所有可能的时间,然后反向检查这个时间需要的 LED 数量是否等于 turnedOn

步骤:

  1. 双重循环:h 从 0 遍历到 11,m 从 0 遍历到 59。
  2. 计算置位(Set Bit):计算 h 的二进制中 1 的个数 + m 的二进制中 1 的个数。
  3. 判断:如果总和等于 turnedOn,则格式化该时间并加入结果集。

复杂度分析:

  • 时间复杂度:$O(1)$。因为循环次数是固定的 720 次,与输入无关,可以看作常数时间。
  • 空间复杂度:$O(1)$。

具体代码

class Solution:
    def readBinaryWatch(self, turnedOn: int) -> List[str]:
        ans = []
        for h in range(12):
            for m in range(60):
                # 检查 h 和 m 的二进制中 1 的总数是否等于 turnedOn
                if (bin(h).count('1') + bin(m).count('1')) == turnedOn:
                    # 格式化:小时正常显示,分钟不足两位补零
                    ans.append(f"{h}:{m:02d}")
        return ans