剑指offer 面试题(打印1到n最大的n位整数)(6)

本文详细介绍了如何通过简单的循环解决打印从1到n最大的n位整数的问题,并针对大整数处理引入了字符串模拟数字加法的算法。进一步通过全排列递归方法实现更深入的理解,旨在提升对数据处理与算法优化的认识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# 面试题: 打印1到n最大的n位整数


/*

题目:  输入数字 n,按顺序打印出从 1 最大的 n位十进制数字。 比如:3,

则打印出 1, 2 ,3 一直到最大的三位数 999;

*/

# 注: 为了方便起见;在开头将头文件和主函数列出,后面只列算法;

   @  方便起见,代码文件以.cpp为格式; 代码中用到 bool型返回值,如果是 .c 文件可以将扩展名改为.cpp,

或者在开头用#define定义三行:
 
                   #define bool int
                   #define true 1
                   #define false 0

#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,然后进位,返回循环是否终止条件;

 其实这个算法实现起来还是蛮难理解的;每一次进来 +1 的时候都得判断每一位的
 
 情况;是都需要进位之类的; 当然如果到了下标为 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;

*/

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!



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值