打印1到最大的n位数

根据输入的数字n,打印1到最大的n位十进制数,如n=3则输出1到999。题目要求处理大数,避免溢出,可以使用字符串或数组表示大数。解决方案包括初始化字符串为全零并逐次加一,或者递归设置每位数字从0到9并输出。
摘要由CSDN通过智能技术生成

       题目:输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999。

       详细可参考《剑指Offer》面试题12,P94。

       本题重点是n的位数不确定,因而用一般的数字类型去存储会溢出,需要考虑大数问题。解决大数问题一般采用字符串或数组来表示大数,这里使用字符串。


       思路一:

       字符串每个数字都初始化为‘0’,然后每一次让字符串表示的数字加1,再打印出来。

       

#include <iostream>
using namespace std;

// false: 代表整个n位数已达最大数
bool IncreaseNumber(char *number)
{
	bool isOverflow = false;
	int flag = 0; // 进位标志
	int length = strlen(number);

	for (int i = length - 1; i >= 0; --i)
	{
		int num = number[i] - '0' + flag; // 每次函数调用number[i]的值已经变化,依次是0~9
		if (i == length - 1) num++; // 如果是个位,直接加1

		if (num >= 10)
		{
			// 需要进位
			if (i == 0) // 如果是第一位(即最高位),若进位,说明已经达到最大数
			{
				isOverflow = true;
			}
			else
			{
				num -= 10; // num继续恢复到0,方便下一位从0开始
				flag = 1; // 进位,使下一位的开始值从0变为1
				number[i] = num + '0'; // 该句之后,for循环跳到字符串的下一位,本位上依旧要从0开始,相当于个位恢复到0,下次for循环从十位开始
			}
		}
		else // 该位数字在10以内,不需要进位
		{
			number[i] = num + '0';
			break; 
		}
	}
	return isOverflow;
}

void PrintNumber(const char* number)
{
	// 注意打印输出时以字符逐个输出,011要输出成11
	bool isBegin0 = true; // 是否以0开头,默认为true
	int length = strlen(number);
	for (int i = 0; i < length; ++i)
	{
		if (isBegin0 && number[i] != '0') // 如果开头不是0,且isBegin0当前值为true的话,就要将isBegin0改为false
		{
			isBegin0 = false;
		}

		// 只有在isBegin0为false时才打印输出
		if(!isBegin0)
		{
			printf("%c", number[i]);
		}
	}
	printf("\t");
}

void Print1toMaxN(int n)
{
	if (n <= 0) return;
	// 用字符串表示大数
	char *number = new char[n + 1];
	if (number == nullptr) return; // 记住:分配内存后检查是否分配成功
	memset(number, '0', n);
	number[n] = '\0'; // 赋初值时别忘了结束标志,别粗心写成了\o

	// 字符串代表的数字每次加1,然后打印输出
	while (!IncreaseNumber(number))
	{
		PrintNumber(number);
	}
}

int main()
{
	int n;
	cin >> n;
	Print1toMaxN(n);

	system("pause");
	return 0;
}

       思路二:

       最大的n位数,即每一位都是0~9的排列,从最低位开始递归,让每个位上从0置为9,然后打印输出。

#include <iostream>
using namespace std;


void PrintNumber(const char *number)
{
	bool isBegin0 = true;
	int length = strlen(number);

	for (int i = 0; i < length; ++i)
	{
		if (isBegin0 && number[i] != '0')
		{
			isBegin0 = false;
		}

		if (!isBegin0)
		{
			printf("%c", number[i]);
		}
	}
	printf("\t");
}

void Print1ToMaxNRecursively(char *number, int length, int index)
{
	if (index == length - 1) // 如果是个位,直接打印
	{
		PrintNumber(number);
		return;
	}

	for (int i = 0; i < 10; ++i)
	{
		number[index + 1] = i + '0';
		Print1ToMaxNRecursively(number, length, index + 1);
	}
}


void Print1ToMaxN(int n)
{
	if (n <= 0) return;
	char *number = new char[n + 1];
	if (number == nullptr) return;
	number[n] = '\0';

	//int length = strlen(number);
	for (int i = 0; i < 10; ++i)
	{
		number[0] = i + '0';
		Print1ToMaxNRecursively(number, n, 0);
	}

	delete[] number; // 别忘了释放内存
}

int main()
{
	int n;
	cin >> n;
	Print1ToMaxN(n);
	system("pause");
	return 0;
}

       虽然递归的方式代码比较简洁,感觉还是有点不好理解,自己走走代码慢慢消化吧。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值