剑指 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 为正整数
考查知识点
字符串表示大数,递归
自己的第一遍解法
直接思路如下:
- 根据
n
获得对应的最大十进制数n_max
- 使用循环将1~
n_max
存入容器
首先来观察一下n
与n_max
的对应关系:
n n_max
1 -> 9
2 -> 99=90+9
3 -> 999=900+90+9
4 -> 9999=9000+900+90+9
从n
到n_max
的映射规律很明显,假设用f(n)
表示n
对应的n_max
的话,有如下递推公式:
f(n) = 9*10^(n-1) + f(n-1)
有了递推公式,使用递归来寻找n_max
就比较形象直接了,代码如下:
//先找到数字n对应的的最大数字,再遍历打印
class Solution {
public:
vector<int> printNumbers(int n) {
if (n < 1) return vector<int> {-1};
int nmax = getNMax(n); //获取数字n对应的最大数字
vector<int> res;
for(int i=1; i<=nmax; ++i)
res.push_back(i);
return res;
}
//求数字n对应的最大数字,1->9, 2->99, 3->999 ...递归实现:f(n) = 10^(n-1) + f(n-1)
int getNMax(int n)
{
if (n == 1) return 9;
int nMax = 0;
nMax =9*pow(10.0, double(n-1)) + getNMax(n-1);
return int(nMax);
}
};
值得注意的是乘方函数pow(double x, double n)
要求传入的底数x
、指数n
都必须为double类型,返回值也是double类型(所以必须做强制类型转换),包含在头文件中。
好的解法
在没有限制n
的大小时,要考虑大数问题,如果n
对应的n_max
非常大,超过int
甚至long long
的最大数值,那么就必须考虑使用字符串或数组来存储。注释得很清楚了。
//使用字符串存储数字,字符串顺序与数字顺序一致
class Solution_jz {
public:
void Print1ToMaxOfNDigits(int n) {
if (n<=0) return;
char *number =new char[n+1];
memset(number, '0', n);
number[n] = '\0';
while (!Increment(number))
PrintNumber(number);
delete [] number;
}
//将用字符串表示的数字+1
bool Increment(char *number)
{
bool isOverflow = false; //第一个字符(即数字最高位)产生进位的标志,为真时表示不能再+1
int nTakeOver = 0; //进位
int nLength = strlen(number);
//从数字最低位开始+1计算进位
for (int i=nLength-1; i>=0; --i)
{
//当前位数字与进位求和
int nSum = number[i] - '0' + nTakeOver;
//数字最低位+1
if (i == nLength-1)
nSum++;
//当前位产生进位
if(nSum >= 10)
{
if (i==0)
isOverflow = true;
else
{
nSum -= 10;
nTakeOver = 1;
number[i] = '0' + nSum;
}
}
//当前位无进位
else
{
number[i] = '0' + nSum;
break;
}
}
return isOverflow;
}
//打印字符串表示的数字
void PrintNumber(char *number)
{
bool isBeginning0 = true;
int nLength = strlen(number);
for(int i=0; i<nLength; ++i)
{
if (isBeginning0 && number[i]!='0')
isBeginning0 = false;
if (!isBeginning0)
cout << number[i] << ' ';
}
cout << endl;
}
};
如果题目是针对n位整数,那么很有可能是考察大数问题,使用字符串表示数字时对某一位字符复制可以使用如下形式:使用字符串nums
表示该大数,num
是第i
位数
nums[i] = '0' + num