本文介绍一种无需存储全部输入、仅需常量空间即可计算磁铁连接后分组数量的优化解法,通过实时比较相邻磁铁类型,显著降低内存占用并简化代码逻辑。
本文介绍一种无需存储全部输入、仅需常量空间即可计算磁铁连接后分组数量的优化解法,通过实时比较相邻磁铁类型,显著降低内存占用并简化代码逻辑。
在经典的“磁铁分组”问题中,每块磁铁以字符串形式给出(仅限 "01" 或 "10"),表示其南北极朝向;当相邻两块磁铁极性相反(即字符串不同)时,它们无法连接,从而形成新的独立组;反之,若相同,则视为可连接(实际物理中同向磁铁会排斥,题目中约定:相同字符串代表同向排斥,故不连接——但注意:题干逻辑实为——只有极性相异才能吸合,而本题中 "01" 和 "10" 本身即代表相反朝向,因此当两个磁铁字符串相同时,说明它们朝向一致、互相排斥,不连接;而字符串不同时,才可能吸合?但根据原始代码与题意惯例,标准理解是:相同字符串表示相同朝向 → 不能吸合 → 属于不同组;不同字符串表示相反朝向 → 可吸合 → 归入同一组。然而,观察原始代码逻辑:if x != nxt: g += 1,即只要当前磁铁与下一个不同,就新增一组**——这显然与物理直觉相悖。
实际上,该题的标准语义是:磁铁按输入顺序排成一行;若相邻两块磁铁朝向相同(即字符串相等),则因同极相斥而断开,形成新组;若朝向相反(字符串不同),则吸合,属于同一组。因此,组数 = 相邻差异次数 + 1,等价于统计有多少次 magnets[i] != magnets[i+1],再加 1。而原始解法正是如此:初始 g = 1,每遇到一次变化就 g += 1。
但原始代码存在明显冗余:
- 使用 list 存储全部 n 个磁铁字符串,空间复杂度 O(n);
- 引入 itertools.tee 实现 pairwise,增加了可读性负担与轻微开销;
- 循环逻辑可进一步精简。
最优解只需保存前一个磁铁类型,逐个读取、即时比较:
n = int(input())
groups = 0
prev = None
for _ in range(n):
current = input().strip()
if current != prev:
groups += 1
prev = current
print(groups)✅ 优势说明:
- 空间复杂度降至 O(1):不再缓存全部输入,仅用两个变量 groups 和 prev;
- 时间复杂度仍为 O(n):单次遍历,无额外迭代;
- 逻辑更直观:每次读到新磁铁,若与前一个不同,意味着连接中断、新组开始;
- 鲁棒性增强:strip() 处理可能的首尾空格;_ 替代 i 表明索引无关紧要。
⚠️ 注意事项:
- 输入保证仅为 "01" 或 "10",无需校验;若需健壮性,可添加 assert current in ("01", "10");
- 当 n == 0 时,上述代码输出 0(合理);若题目保证 n ≥ 1,则无需特殊处理;
- 此解法本质是“游程编码(Run-length encoding)”思想的应用:统计连续相同元素的段数。
总结:算法优化不只关乎行数缩减,更在于模型抽象——将问题转化为「统计状态切换次数」,即可摆脱数据容器依赖,实现清晰、高效、可扩展的实现。

















