1. 问题背景与定义解析
今天想和大家分享一道经典的面试编程题——「旋转数字」。这道题看似简单,但考察了候选人对问题分析、边界条件处理以及代码实现细节的把控能力。我在实际面试中多次遇到候选人在这道题上栽跟头,主要原因是没有完全理解题目要求。
1.1 什么是「好数」?
题目定义了一个特殊概念——「好数」。具体来说,一个数字如果满足以下三个条件,就被称为好数:
- 数字的每一位旋转180度后仍是有效数字(即不能包含3、4、7这些旋转后无效的数字)
- 旋转后的数字与原数字不相同(即至少包含2、5、6、9这些旋转后会变化的数字)
- 数字的每一位都必须参与旋转(这个条件通常隐含在前两个条件中)
举个例子,数字"69"旋转180度后变成"69",但因为6和9互相转换,实际上变成了"69"(看起来一样但内部已经变化),所以它满足好数定义。而数字"88"旋转后仍然是"88",不满足第二个条件。
1.2 数字旋转特性详解
理解数字旋转后的变化是解题的关键。我们可以将所有数字分为三类:
| 数字类型 | 包含数字 | 旋转特性 | 对好数的影响 |
|---|---|---|---|
| 无效数字 | 3、4、7 | 旋转后非数字 | 包含则直接排除 |
| 变化数字 | 2、5、6、9 | 旋转后变成其他数字 | 必须至少包含一个 |
| 不变数字 | 0、1、8 | 旋转后仍为自身 | 仅包含这些数字时不是好数 |
注意:数字"6"旋转后变成"9","9"旋转后变成"6","2"和"5"互相转换。这种对称性变化是判断的关键。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路与算法设计
2.1 暴力解法:逐数检查
最直观的解法是对1到N的每个数字进行逐位检查:
- 遍历从1到N的每个数字
- 对每个数字,检查其每一位:
- 如果发现3、4、7中的任意一个,立即排除
- 如果包含2、5、6、9中的至少一个,标记为候选
- 最终统计满足条件的数字数量
这种解法的时间复杂度是O(N*d),其中d是数字的平均位数。对于N≤10000的常规面试题范围,这个复杂度完全可接受。
2.2 优化思路:数位DP
虽然暴力解法在面试中通常足够,但如果N非常大(比如1e9),我们
