LeetCode 401 - 二进制手表


文章目录

摘要

这道题其实是一个非常典型的组合枚举问题。我们有 10 个 LED 灯,其中 4 个代表小时(范围 0--11),6 个代表分钟(范围 0--59),题目要求我们给出所有"亮灯数 = turnedOn"时的合法时间组合。

看起来像是个电子表的问题,但本质上是二进制位运算与组合的应用。我们可以把"亮灯的数量"理解成"二进制 1 的个数",所以整个题的核心思路就是:枚举所有可能的小时和分钟组合,筛选出二进制中 1 的个数刚好等于 turnedOn 的情况。

描述

在一个二进制手表上:

  • 上面 4 个 LED 代表小时(0~11),用 4 位二进制来表示;
  • 下面 6 个 LED 代表分钟(0~59),用 6 位二进制来表示。

举例:

  • 小时 4 = 0100
  • 分钟 51 = 110011
    那么时间是 "4:51"

我们要做的就是:给定亮着的灯的数量 turnedOn,输出所有符合这个亮灯数的时间,比如当 turnedOn = 1 时,只有一个 LED 亮着,那么可能是 "1:00""0:08""0:32" 等。

题解答案

最直观的想法是暴力枚举所有可能的小时和分钟:

  • 小时范围 [0, 11]
  • 分钟范围 [0, 59]

对于每个组合:

  1. 计算当前小时和分钟的二进制表示;
  2. 求两者中 1 的总数;
  3. 如果等于 turnedOn,就把格式化后的时间加入结果。

Swift 提供了内置的函数 nonzeroBitCount,可以直接获取一个整数的二进制中 1 的数量,非常适合这种情况。

题解代码分析

下面我们来写一个完整可运行的 Swift Demo:

swift 复制代码
import Foundation

class Solution {
    func readBinaryWatch(_ turnedOn: Int) -> [String] {
        var result: [String] = []
        
        // 枚举小时和分钟
        for hour in 0..<12 {
            for minute in 0..<60 {
                // 计算二进制中1的个数
                if hour.nonzeroBitCount + minute.nonzeroBitCount == turnedOn {
                    // 格式化时间
                    let time = String(format: "%d:%02d", hour, minute)
                    result.append(time)
                }
            }
        }
        
        return result
    }
}

// 示例测试
let sol = Solution()
print(sol.readBinaryWatch(1))
print(sol.readBinaryWatch(2))
print(sol.readBinaryWatch(9))

代码解析

  1. hour.nonzeroBitCount:这是 Swift 的一个非常实用的属性,用来计算整数中 1 的数量,相当于 C++ 的 __builtin_popcount
  2. 我们遍历所有可能的时间组合,共 12 * 60 = 720 种。
  3. 只要当前时间的二进制亮灯数与输入的 turnedOn 相同,就把这个时间加入结果。
  4. String(format: "%d:%02d", hour, minute) 保证分钟是两位数格式,比如 "1:05"

整个逻辑非常直观,核心是利用二进制的位数统计来筛选。

示例测试及结果

示例 1

输入:

swift 复制代码
sol.readBinaryWatch(1)

输出:

复制代码
["0:01","0:02","0:04","0:08","0:16","0:32",
 "1:00","2:00","4:00","8:00"]

解释:

  • 当只有一个灯亮时,可能是某个分钟灯亮,也可能是某个小时灯亮。

示例 2

输入:

swift 复制代码
sol.readBinaryWatch(9)

输出:

txt 复制代码
[]

解释:

手表最多有 10 个灯,小时最多 4 位 + 分钟 6 位;如果亮 9 个灯,不可能构成合法时间。

示例 3

输入:

swift 复制代码
sol.readBinaryWatch(3)

输出示例:

txt 复制代码
["0:07", "0:11", "1:03", "2:05", "3:00", "4:06", "8:03", ...]

时间复杂度

  • 枚举所有小时(12 种)和分钟(60 种),总共 720 次循环。
  • 每次循环只做常数级别操作(位数统计 + 拼接字符串)。
    所以时间复杂度为 O(720) ,即 O(1) 常数级。

空间复杂度

只使用了一个结果数组,没有额外结构。

空间复杂度为 O(1)(不计输出结果)。

总结

这题是一个非常典型的"枚举 + 二进制位计数"问题。

虽然题目看起来和时间有关,但其实本质是一个组合问题:有 10 个灯,开了几个,就代表一个唯一的小时+分钟组合。

相关推荐
papership17 分钟前
【入门级-算法-5、数值处理算法:高精度的乘法】
数据结构·算法
earthzhang202118 分钟前
【1039】判断数正负
开发语言·数据结构·c++·算法·青少年编程
谈笑也风生21 分钟前
只出现一次的数字 II(一)
数据结构·算法·leetcode
蕓晨21 分钟前
auto 自动类型推导以及注意事项
开发语言·c++·算法
mjhcsp1 小时前
C++ 递推与递归:两种算法思想的深度解析与实战
开发语言·c++·算法
_OP_CHEN1 小时前
算法基础篇:(三)基础算法之枚举:暴力美学的艺术,从穷举到高效优化
c++·算法·枚举·算法竞赛·acm竞赛·二进制枚举·普通枚举
m0_748248021 小时前
《详解 C++ Date 类的设计与实现:从运算符重载到功能测试》
java·开发语言·c++·算法
天选之女wow1 小时前
【代码随想录算法训练营——Day61】图论——97.小明逛公园、127.骑士的攻击
算法·图论
aloha_7891 小时前
测试开发工程师面经准备(sxf)
java·python·leetcode·压力测试
im_AMBER2 小时前
Leetcode 47
数据结构·c++·笔记·学习·算法·leetcode