# 面试题: 打印1到n最大的n位整数
/*
题目: 输入数字 n,按顺序打印出从 1 最大的 n位十进制数字。 比如:3,
则打印出 1, 2 ,3 一直到最大的三位数 999;
*/
# 注: 为了方便起见;在开头将头文件和主函数列出,后面只列算法;
@ 方便起见,代码文件以.cpp为格式; 代码中用到 bool型返回值,如果是 .c 文件可以将扩展名改为.cpp,
或者在开头用#define定义三行:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
int main()
{
int n = 2;
Print_MaxNum(n);//打印最大位整数;
system("pause");
return 0;
}
例题分析: 首先,看到这道题的时候,我略微一思索,这就是个简单的循环问题,于是我快速的写下了如下的代码:
void Print_MaxNum(int num)
{
if(num <= 0)
{
return ;
}
int i = 0;
for(i = 1; i < pow(10.0,num); i++)
{
printf("%d\n", i);
}
}
# 乍一看,是不是觉得没什么问题! 但是如果给个足够大的数,int,long都放不下的时候怎么办?
#那么,仔细思索之后,便有了字符串上模拟数字加法的算法! 最大的整数是几位,我们就开辟多大的字符串;
假设1到最大的3位数:
char *num = "000"; 然后+1 每加一次就输出一次;知道最大的三位数 999 停止;
看着似乎挺好理解,但是当你真正实现代码的时候,你才会理解,其实有些复杂,我也是仔细阅读剑指offer的代码好
几遍才理解!

那么就开始算法吧!
/*
函数: Print_MaxNum;
在这个函数里面我们有封装了两个函数,可以让算法思路可以更加清晰;
注意:为了方便起见,在这里直接用C++里面的 new和delete 来分配空间;
如果你不懂,可以用malloc动态开辟;或者自己定义一个数组;
@memset 函数是将数组num中的内容都置为'0';是内存操作函数;有兴趣的
同学可以了解一下;
*/
void Print_MaxNum(int n)
{
if(n <= 0)
return ;
char *num = new char[n+1];
memset(num,'0',n);
num[n] = '\0';//因为是字符串,所以别忘了'\0';
while(!Judge(num))
{
print(num);
}
delete []num;//new和delete成对使用,和malloc,free一样;
}
# 先来实现 Judge 函数:
/*
Judge函数的功能就是给每个数 +1,然后进位,返回循环是否终止条件;
Judge函数的功能就是给每个数 +1,然后进位,返回循环是否终止条件;
其实这个算法实现起来还是蛮难理解的;每一次进来 +1 的时候都得判断每一位的
情况;是都需要进位之类的; 当然如果到了下标为 0 的位的时候还需要进位;
则循环终止;举个例子 要打印最大的三位数; 到了999 的时候需要 +1 了;但是
999已经是最大的三位数了,那么就该结束了;
算法理解起来有些晦涩;需要反复琢磨!
*/
情况;是都需要进位之类的; 当然如果到了下标为 0 的位的时候还需要进位;
则循环终止;举个例子 要打印最大的三位数; 到了999 的时候需要 +1 了;但是
999已经是最大的三位数了,那么就该结束了;
算法理解起来有些晦涩;需要反复琢磨!
*/
bool Judge(char *num)//每次增加1,并且判断循环是否终止;
{
bool isOverflow = false;//判断是都结束循环
int isJinWei = 0;//低位向高位的进位
int i = 0;
int opnum = 0; //方便在函数内进行加减设置的整形操作数;
int length = strlen(num);
/*
接下来就是对每一位的判断;并且进行+1操作;
@要注意的 一进入循环就应该立马加上进位数;再进行判断;
@如果当前位>= 10,需要进位,将isJinWei 置为 1;表示要进1;
@千万不要忘记进位之后将 整形操作数 opnum 减去10;因为你已经进位了;
*/
for(i = length - 1; i >= 0; i--)
{
opnum = num[i] - '0' + isJinWei ;
if(i == length - 1)
opnum++; //最低位加 1;
if(opnum >= 10)
{
if(i==0)
isOverflow = true;
else
{
opnum -= 10;
isJinWei = 1;
num[i] = '0' + opnum;
}
}
else
{/*
如果不需要进位则将操作数加上去;注意数组里存放的是字符型;
要加上‘0’才行;
*/
num[i] = '0' + opnum;
break;
}
}
return isOverflow ;//注意返回值类型是bool
}
#接下来 print函数
/*
为什么要单独实现一个print函数呢? 这其实是这道题的一个亮点;
你想想,数组前面没有用到的位都被我们置为 '0'了;那么输出来岂不是成了这样:
00001
00002
……
00098
00099
这不太符合我们的阅读习惯,那么这个print函数的功能就是不输出多余的0;
00001
00002
……
00098
00099
这不太符合我们的阅读习惯,那么这个print函数的功能就是不输出多余的0;
*/
void print(char *num)
{
bool isbegining0 = true;
int length = strlen(num);
int i =0;
for(i = 0; i < length; i++)
{
if(isbegining0 && num[i] != '0')
isbegining0 = false;
if( !isbegining0 )
printf("%c",num[i]);
}
printf("\n");
}
/*
这样,这个算法也就完了; 但是:
@ Judge 函数还可以全排列方法实现, 使用递归; 我能看懂但是 我觉得我讲不清,所以我只把代码列出来,不做
解释,仅供参考! //代码里的print函数和上面是一样的!
*/
全排列递归实现代码:
// 全排列递归实现
void JudgeAchieve(char *num,int length, int index)
{
if(index == length - 1)
{
print(num);
return ;
}
for(int i = 0; i < 10; ++i)
{
num[index + 1] = i + '0';
JudgeAchieve(num,length,index+1);
}
}
void Judge(int n)
{
if(n <= 0)
return ;
char *num = new char[n+1];
num[n] = '\0';
for(int i = 0; i < 10; ++i)
{
num[0] = i + '0';
JudgeAchieve(num,n,0);
}
delete []num;
}
Ps: 不动起来,你都不知道自己是多么强大!
over, Thanks!