Advent of Code 2025 挑战全手写代码 Day 2 - 礼品店

🎄Advent of Code 2025 挑战全手写代码 Day 2 - 礼品店


第二天题目 Gift Shop,难度简单(1.5 星 ⭐),主要考察字符串处理枚举

📖 题目速览
advent-of-code-2025-day2

题目地址:https://adventofcode.com/2025/day/2

北极基地的礼品店数据库被小精灵搞乱了,输入了一堆无效的商品 ID。我们需要在给定的多个数字范围内(例如 11-22, 95-115),找出所有符合特定“重复模式”的“无效 ID”。

Part 1: 找出由重复两次的数字序列组成的 ID(如 123123)。
Part 2: 找出由重复至少两次的数字序列组成的 ID(如 123123123111)。

例如:

  • 55 (5重复) -> Part 1 & 2 无效 ❌
  • 123123 (123重复) -> Part 1 & 2 无效 ❌
  • 111 (1重复三次) -> Part 1 有效 ✅,但 Part 2 无效 ❌
  • 101 -> 有效 ✅
  • 0101 -> 题目规定无前导零,不是 ID

任务:找出所有范围内符合条件(无效)的 ID 并求和。

💡 解题思路 (Python 🐍)

今天的核心是判断一个数字是否符合“重复模式”。

  1. 解析输入:输入是一长串逗号分隔的范围 start-end,先用 split 处理成 (start, end) 元组列表。

  2. 暴力枚举 (Part 1 & 2)
    因为我们是直接提交答案而不是在线实时运行,对时间的要求可以放宽。最直接的方法就是遍历范围内每一个数字,转成字符串判断。

    def _is_invalid_1(self, num: int) -> bool:
        s = str(num)
        length = len(s)
        # Part 1: 长度必须是偶数,且前半段等于后半段
        if length % 2 != 0:
            return False
        return s[:length//2] == s[length//2:]
    

    Part 2 规则升级(重复次数 >= 2),我的解法是枚举所有可能的“子串长度” delta,检查数字是否由该子串重复构成。

    def _is_invalid_2(self, num: int) -> bool:
        s = str(num)
        half = len(s) // 2
        # 尝试所有可能的循环节长度
        for delta in range(1, half + 1):
            if len(s) % delta == 0:
                # 将字符串切分为长度为 delta 的片段
                parts = [s[i:i+delta] for i in range(0, len(s), delta)]
                # 检查所有片段是否相同
                if all(p == parts[0] for p in parts[1:]):
                    return True
        return False
    

✨ 代码复盘 & 优化思考

虽然上面的解法能过,但作为算法爱好者,不得不反思一下:

  1. 当前的“笨”解法
    我是老老实实遍历了 range 里的每一个数字去检查。如果题目给的范围是 1100亿,这种 O ( N ) O(N) O(N) 的解法直接原地爆炸 💥。这就好比为了找“四叶草”,把整片草地的每一根草都拔起来看一遍。

  2. 更优的“生成式”思路
    其实符合 AB...AB... 这种重复模式的数字是非常稀疏的。
    与其“检查”,不如“构造”。

    • 比如要找 6 位以内的目标数,我只需要枚举 1999 (作为前半段 S S S)。
    • 然后把 S S S 拼成 S S SS SS (如 123 -> 123123)。
    • 直接看这个 S S SS SS 在不在题目给的 range 里就行了。
    • 这种方法复杂度瞬间降到 O ( N ) O(\sqrt{N}) O(N ),效率提升几个数量级!🚀

虽然 Day 2 用“笨”方法可以解,但保持对复杂度的敏感度是必要的!💪

完整代码:访问 github

Happy Coding! 今天也要继续冲榜!🚀

day-2-ranking

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值