打印1到最大的n位數

       題目:輸入數字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;
}

       雖然遞歸的方式代碼比較簡潔,感覺還是有點不好理解,自己走走代碼慢慢消化吧。




發佈了52 篇原創文章 · 獲贊 124 · 訪問量 19萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章