文章目录
- 题目
- 思路
- 代码
题目
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
说明:
用返回一个整数列表来代替打印
n 为正整数
来源:力扣(LeetCode)
思路
在力扣里这道题不用考虑大数。但是还是想自己写一个以备不虞。
重点:
- 用
string
处理大数。 - 处理每一位时,将
int
转换为char
。 - 用
递归+分治
的思想生成位数n
对应的全排列
。 - 将生成的全排列依次压入
vector<int>
中,按题目要求返回整数列表。
细节:
-
第一点无需赘述。
-
关于第二点:
我们知道 string
每一位下标对应的元素其类型都是 char
的(字符串由字符组成嘛)。
那代码实现应该怎么写呢?是这样吗?
s[digit] = (char)i;
答案是否定的。来看这么一段代码:
可以看到输出结果不是4,而是52。
简单的 (char)i
起到的作用是将 i
变为 ASCII码为i的字符
,上图中,因为字符’4’ 的ASCII码为52,因此 char(52)
会得到 字符'4'
。
换言之,s[digit] = (char)i;
得到的是 ASCII码为i时对应的字符
,而非 字符'i'
。
正确处理 int
转 char
应为(例如:将整数4转换为字符4):
上图代码的本质也就是 0的ASCII码(48)+4
得到 ASCII码52
,其对应的字符便是 '4'
。
值得一提的是,通过 + '0'
将 int
转换为 char
并非总是可行的。当整数大于9时, + '0'
操作得到的便不再是数字字符了:
当然对于本题来讲并不存在这样的问题,因为我们仅仅是转换每个数位上的数字(它们在0~9之间)。
- 关于第三点,也是本题最重要的部分:
全排列思想如下图所示(图源大佬:jyd):
代码中用 dfs函数
实现:
- 用分治思想先固定高位(digit=0)
string[digit]
(图中蓝色部分) - 再依次固定低位(digit+1),将
digit+1
作为新参数传入函数dfs
(图中红色部分) - 当
digit == n
时,此时已将每一位都处理完了,将string转换为int,并判断int是否为0,不为0则加入用来保存结果的vector<int>
。(将string转换为int
之后的操作仅仅是针对本题要求的返回证书列表,如果真的需要考虑大数的情况应该返回vector<string>
。) - 经过上面三步仅仅处理完了高位0~9中的一种情况,接下来应该改变高位的值,重复上述步骤,直至处理完高位为9的情况,才真正完成了整个全排列的流程。
代码
class Solution {vector<int> iv;void dfs(int n, int digit, string& s){if(n == digit){ // 位数处理完毕int val = std::stoi(s);if(val){iv.push_back(val); }return;}for(int i = 0; i < 10; i++){s[digit] = i + '0'; // int -> chardfs(n, digit+1, s);}}
public:vector<int> printNumbers(int n) {string s(n, '0');dfs(n, 0, s);return iv;}
};