剑指 Offer 17. 打印从1到最大的n位数
- 题目描述
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
说明:
用返回一个整数列表来代替打印
n 为正整数
- 分析
简单做法这里就不记录了,虽然在python里面不考虑大数越界问题,但是面试的时候要是就仅仅手写个for循环+append,肯定offer就凉了。
因此,可以考虑将打印数的问题转化为打印string的全排列问题,可以看这个图理解排列过程:
就是从n位到各位逐渐求0~9的排列组合。因此可以用递归实现,递归的思想是:
向低位递归,当个位已经被固定时,添加数字的字符串,例如n=2时,固定十位0~9,递归最小规模为当递归到个位数时,添加数字字符串。
但是,仅仅这样输出的是元素为string的list,并且存在01 02 010 099 这样的前面带0的数,因此我们还需要去前面的0才是最终的打印出来正常的数字。
(这里其实我就理解得不是很透彻了)
删除高位数字:
1.字符串左边界定义:设定start为左边界,用nums[start:]控制输出的不为零的数
2.左边界start的变化规律:观察可知,当输出数字的所有位都是 99 时,则下个数字需要向更高位进 11 ,此时左边界 startstart 需要减 11 (即高位多余的 00 减少一个)。例如当 n = 3n=3 (数字范围 1 - 9991−999 )时,左边界 start 需要减 1的情况有: "009" 进位至 "010" , "099" 进位至 "100" 。设数字各位中 99 的数量为 nine,所有位都为 99的判断条件可用以下公式表示:
n−start=nine
3.统计nine的方法:固定第x位,当i=9,则nine=nine+1,并且一定要在回溯前回复nine=nine-1
代码
class Solution: def printNumbers(self, n: int) -> [int]: def dfs(x): if x == n: # 终止条件:已固定完所有位 s = ''.join(num[self.start:]) #res.append(''.join(num)) # 拼接 num 并添加至 res 尾部 if s != '0': res.append(int(s)) if n - self.start == self.nine: self.start -= 1 return for i in range(10): # 遍历 0 - 9 if i == 9: self.nine += 1 num[x] = str(i) # 固定第 x 位为 i dfs(x + 1) # 开启固定第 x + 1 位 self.nine -= 1 num = ['0'] * n # 起始数字定义为 n 个 0 组成的字符列表 res = [] # 数字字符串列表 self.nine = 0 self.start = n -1 dfs(0) # 开启全排列递归 return res