LeetCode 967. 连续差相同的数字
题目描述


题意分析
返回所有恰好有
n位、相邻两位数字的差的绝对值都等于k的非负整数,结果顺序不限。多位整数不能有前导零,但首位之后允许出现零。题目保证
2 <= n <= 9、0 <= k <= 9。条件约束每一对相邻数位,不是要求整个数递增,也不是只比较首尾。因为位数至少为二,起始数位只能选择一到九。
解法:按位扩展构造数字
核心思路
[!blue]
一个合法前缀已经满足其内部所有相邻位的条件,追加下一位时,只需要检查新数位与当前末位的差。因此可以从一位数开始,按长度一层一层扩展,而不用枚举全部
n位整数再筛选。用
cur保存当前长度的所有合法前缀,初始为一到九。对每个前缀num,末位为last = num % 10,下一位只能是last + k或last - k。保留落在零到九之间的候选,用num * 10 + digit把它追加到末尾。每轮创建独立的
next,只从旧长度的cur生成新长度前缀,再用next替换cur。这样处理完长度level的一轮后,集合中所有数都恰好是这个位数,不会把同一轮刚生成的更长结果继续扩展。当
k = 0时,加减得到同一个下一位,只生成其中一支;当k > 0时,两支不同。不同前缀追加数位后也不可能变成同一个整数,因为删除末位就能唯一还原原前缀。因此处理好零差分支后,无需额外集合去重。任意合法整数都有合法的首位和逐位前缀,且每一步的下一位都属于上述两个候选,所以按层扩展不会漏解。只追加满足差值和数位范围的候选,也保证生成的全部结果合法。
解题步骤
- 将一到九加入
cur,表示所有合法的一位前缀。- 让
level从二增加到n,每轮创建空next。- 对每个当前前缀,计算末位,尝试追加不大于九的
last + k。- 若
k != 0且last - k >= 0,再追加这一候选,避免零差时重复。- 用
next替换cur;构造完n位后返回这一层。
代码实现
class Solution {
public int[] numsSameConsecDiff(int n, int k) {
List<Integer> cur = new ArrayList<>();
for (int i = 1; i <= 9; i++) {
cur.add(i);
}
for (int level = 2; level <= n; level++) {
// 当前层只保存增加一位后的结果。
List<Integer> next = new ArrayList<>();
for (int num : cur) {
int last = num % 10;
int high = last + k;
int low = last - k;
if (high <= 9) {
next.add(num * 10 + high);
}
// 差为零时两个候选相同,不重复加入。
if (k != 0 && low >= 0) {
next.add(num * 10 + low);
}
}
cur = next;
}
int[] res = new int[cur.size()];
for (int i = 0; i < cur.size(); i++) {
res[i] = cur.get(i);
}
return res;
}
}
func numsSameConsecDiff(n int, k int) []int {
cur := make([]int, 0)
for i := 1; i <= 9; i++ {
cur = append(cur, i)
}
for level := 2; level <= n; level++ {
// 当前层只保存增加一位后的结果。
next := make([]int, 0)
for _, num := range cur {
last := num % 10
high := last + k
low := last - k
if high <= 9 {
next = append(next, num*10+high)
}
// 差为零时两个候选相同,不重复加入。
if k != 0 && low >= 0 {
next = append(next, num*10+low)
}
}
cur = next
}
return cur
}
复杂度分析
- 时间复杂度:与全部层处理的前缀数量之和成正比。首层九个前缀,每个前缀最多扩展两支,总上界为 $O(9\cdot 2^{n-1})$。
- 空间复杂度:$O(9\cdot 2^{n-1})$ 上界,同时保存当前层和下一层;实际数量会因数位范围限制而减少。
关键点总结
[!green]
- 已合法前缀只需检查最后一位与新数位,局部条件即可逐层保证整体合法。
- 首位不为零与后续位可以为零是不同限制。
- 独立新层控制位数,
k = 0时只走一支控制重复。
易错点总结
[!yellow]
- 从零开始构造多位前缀,会产生不合法的前导零数字。
- 把差的绝对值要求理解成只能加
k,会漏掉允许递减的相邻数位。- 不检查候选是否位于零到九,就可能把负数或两位数当作单个数位追加。
- 零差时仍加入加减两支,会重复生成同一个数字。
- 把新前缀混入当前集合继续遍历,会失去每层位数一致的保证。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 1291. 顺次数 | 中等 | 原题只允许后一数码比前一数码大1,本题允许上下两个方向且绝对差固定为k。 |
| 17. 电话号码的字母组合 | 中等 | 同样逐位置枚举合法字符选项,本题下一位选项由前一数码与k决定。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!