剑指 Offer 17. 打印从 1 到最大的 n 位数

“对于程序员而言,刷了Leetcode不一定能拿offer,但是不刷肯定拿不到offer。”

Lusion鲁迅

Lusion

剑指 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 为正整数

大数问题

简单来看,遍历计算即可获取答案,由于要求返回的是int[],故不会出现溢出情况。

如果要求返回的是String,则是考察大数问题的处理。
$$
T(n) = O(10^n)
$$

$$
V(n) = O(10^n)
$$

String处理进位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
public int[] printNumbers(int n) {
int[] res = new int[(int)Math.pow(10, n) - 1];
StringBuilder str = new StringBuilder();
for (int i = 0; i < n; i++) {
str.append('0');
}
int count = 0;
while(!increment(str)) {
int index = 0;
while (index < str.length() && str.charAt(index) == '0'){
index++;
}
res[count++] = Integer.parseInt(str.toString().substring(index));
}
return res;
}

private boolean increment(StringBuilder str) {
boolean isCarry = false;
for (int i = str.length()-1; i >= 0; i--) {
char s = (char)(str.charAt(i) + 1);
if (s > '9') {
str.replace(i, i+1, "0");
if (i == 0) {
isCarry = true;
}
} else {
str.replace(i, i+1, String.valueOf(s));
break;
}
}
return isCarry;
}
}

dfs全排列

由于在09999这种情况下,会出现连续进位,遍历n-1次,需要从最低位到最高位循环判断,所以可以考虑全排列避开进位操作。(通过递归实现全排列,生成String列表)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
int[] res;
int nine = 0, count = 0, start, n;
char[] num, loop = {'0','1','2','3','4','5','6','7','8','9'};

public int[] printNumbers(int n) {
this.n = n;
res = new int[(int)Math.pow(10,n)-1];
num = new char[n];
start = n - 1;
dfs(0);
return res;
}

private void dfs(int x) {
if (x == n) {
String s = String.valueOf(num).substring(start);
if (!s.equals("0")) res[count++] = Integer.parseInt(s);
if (n - start == nine) start--;
return;
}
for (char i : loop) {
if (i == '9') nine++;
num[x] = i;
dfs(x+1);
}
nine--;
}
}
文章目录
  1. 1. 剑指 Offer 17. 打印从 1 到最大的 n 位数
    1. 1.1. 大数问题
      1. 1.1.1. String处理进位
      2. 1.1.2. dfs全排列
|