面试题17:打印从 1 到最大的 n 位数
题目描述
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
解法一:大数加法
思路:
- 当 n 过于大时,无论是 int 还是 long long 都会出现溢出,考虑至此,我们选择使用数组来处理大数问题
- 由于每一位上面数字范围是 [0, 9] 共 10 个数字,故我们考虑使用 char 型数组,而 int 型数组过于浪费空间
- 最大的 n 位数字,即需要打印直到 n 个 9 的时候即可
- 如何判断是否到最大呢?
- 策略 1:使用 strcmp 函数比较字符串与"999…999",可是 strcmp 时间复杂度为O(N),不太好
- 策略 2:判断第 n+1 位是否发生进位,时间复杂度为 O(1),可行!
- 如何打印呢?
- 策略 1::使用 print 函数,但是会把字符串前面没有数字的 0 都给打印出来,这样不太好
- 策略 2:遍历字符串,把前面的 0 全部略过,出现数字再打印
bool Increment(char *s)
{
bool flag = false;
int nextDig = 0;
for (int i = strlen(s) - 1; i >= 0; i--)
{
int curNum = s[i] - '0' + nextDig;
if (i == strlen(s) - 1)
curNum++;
if (curNum > 9)
{
if (i == 0)
{
flag = true;
}
else
{
nextDig = 1;
curNum -= 10;
s[i] = curNum + '0';
}
}
else
{
s[i] = curNum + '0';
break;
}
}
return flag;
}
void PrintS(char* s)
{
int i;
for (i = 0; i < strlen(s); i++)
{
if (s[i] != '0') break;
}
for (; i < strlen(s); i++)
{
printf("%c", s[i]);
}
}
void PrintToMaxOfNDigits(int n)
{
if (n <= 0) return;
char* s = new char[n + 1];
memset(s, '0', n);
s[n] = '\0';
while (!Increment(s))
{
PrintS(s);
putchar('\n');
}
delete[] s;
}
解法二:全排列
思路:
- n 位数字从 0 到 9 的全排列
- 打印时,前面的 0 不打印出来
void PrintS(char* s)
{
int i;
for (i = 0; i < strlen(s); i++)
{
if (s[i] != '0') break;
}
for (; i < strlen(s); i++)
{
printf("%c", s[i]);
}
}
void func(char* s, int n, int index)
{
if(index == n-1)
{
PrintS(s);
return ;
}
for(int i = 0; i < n ;i++)
{
s[i] = '0' + i;
func(s, n, i);
}
}
void PrintToMaxOfNDigits(int n)
{
if(n <= 0) return ;
char* s = new char[n+1];
s[n] = '\0';
func(s, n, 0);
delete[] s;
}