面试题17:打印从1到最大的n位数
题目:输入数字n,按顺序打印出从1到最大的n位十进制数
分析:由于n未知,可能是非常大的数,常规的数据类型可能装不下,考虑用字符串数组来存储数字,但需要考虑一下两个问题:
- 字符串数组表示数字的相加算法(通过模拟十进制数的加法过程完成或其他方法);
- 规范得打印出数字。
代码:
#include <stdio.h>
///
///题目:打印1到n位的最大数(考虑大数问题,用字符串来表示数字)
///
void print1toNMaxRecursively(int n);
//字符窜表示的数字自增1,返回值表示是否溢出
bool charNumberIncrease(char *number, int length);
//打印字符窜表示的数字
void printCharNumber(char *number, int length);
int main()
{
print1toNMaxRecursively(5);
return 0;
}
void print1toNMaxRecursively(int n)
{
if (n <= 0)
{
return;
}
char *number = new char[n + 1];
for (int i = 0; i < n; i++)
{
number[i] = '0';
}
number[n] = '\0';
while (!charNumberIncrease(number, n))
{
printCharNumber(number, n);
}
}
//字符窜表示的数字自增1
bool charNumberIncrease(char *number, int length)
{
bool isOverflow = false;
int takeOver = 0;
int sum = 0;
for (int i = length - 1; i >= 0; i--)
{
sum = number[i] - '0' + takeOver;
if (i == length - 1)
{
sum++;
}
if (sum >= 10)
{
if (i == 0)
{
isOverflow = true;
}
else
{
sum -= 10;
takeOver = 1;
number[i] = sum + '0';
}
}
else
{
number[i] = sum + '0';
break;
}
}
return isOverflow;
}
//打印字符窜表示的数字
void printCharNumber(char *number, int length)
{
bool isBeginPrint = false;
for (int i = 0; i < length; i++)
{
if (!isBeginPrint && number[i] != '0')
{
isBeginPrint = true;
}
if (isBeginPrint)
{
printf("%c", number[i]);
}
}
printf(",");
}
除了通过模拟十进制数的加法过程来完成以外,还可以通过全排列的思路完成:由于是打印出1到n位的最大数,那么可以将改问题看成打印n位数的全排列,以下通过递归的方式编写代码:
void print1toNMaxRecursively(int n)
{
if (n <= 0)
{
return;
}
char *number = new char[n + 1];
for (int i = 0; i < n; i++)
{
number[i] = '0';
}
number[n] = '\0';
for (int i = 0; i < 10; i++)
{
number[0] = i + '0';
print1toNMaxRecursiveCore(number, n, 0);
}
delete[] number;
}
//全排列打印的核心函数
void print1toNMaxRecursiveCore(char *number, int length, int index)
{
if (index == length - 1)
{
printCharNumber(number, length);
return;
}
for (int i = 0; i < 10; i++)
{
number[index + 1] = i + '0';
print1toNMaxRecursiveCore(number, length, index + 1);
}
}
相关题目:计算两个大数相加的结果(只考虑正数)
代码:
///
///题目:两个大数相加(只考虑正数),输入:三行,第一行输入相加两数的最大位数N,后两行分别输入一个大数
///
#include <iostream>
#include <stdio.h>
using namespace std;
//两个字符串表示的大数相加
char *addBigNumber(char *num1, char *num2, int maxLength);
//打印字符窜表示的数字
void printCharNumber(char *number, int length);
int main()
{
cout << "input three line:N:max bit and two big number" << endl;
int N = 0;
cin >> N;
char *num1 = new char[N + 1];
char *num2 = new char[N + 1];
cin >> num1;
cin >> num2;
char *sum = addBigNumber(num1, num2, N);
if (sum != NULL)
{
cout << "sum:";
printCharNumber(sum, N + 1);
}
return 0;
}
//两个字符串表示的大数相加
char *addBigNumber(char *num1, char *num2, int maxLength)
{
if (maxLength <= 0)
{
return NULL;
}
int index1 = 0, index2 = 0;
for (; num1[index1] != '\0'; index1++)
{
if (!(num1[index1] >= '0' && num1[index1] <= '9'))
{
cout << "invali input!" << endl;
return NULL;
}
}
for (; num2[index2] != '\0'; index2++)
{
if (!(num2[index2] >= '0' && num2[index2] <= '9'))
{
cout << "invalid input!" << endl;
return NULL;
}
}
index1--;
index2--;
int max = index1 > index2 ? index1 : index2;
if (maxLength < max)
{
cout << "invali input!" << endl;
return NULL;
}
//预留一位,防止溢出
char *sum = new char[maxLength + 2];
sum[maxLength + 1] = '\n';
int takeOver = 0;
for (int i = maxLength; i >= 0; i--)
{
int n1 = 0, n2 = 0;
if (index1 >= 0)
{
n1 = num1[index1] - '0';
}
if (index2 >= 0)
{
n2 = num2[index2] - '0';
}
int temp = n1 + n2 + takeOver;
if (temp >= 10)
{
temp -= 10;
takeOver = 1;
sum[i] = temp + '0';
}
else
{
sum[i] = temp + '0';
takeOver = 0;
}
index1--;
index2--;
}
return sum;
}
//打印字符窜表示的数字
void printCharNumber(char *number, int length)
{
bool isBeginPrint = false;
for (int i = 0; i < length; i++)
{
if (!isBeginPrint && number[i] != '0')
{
isBeginPrint = true;
}
if (isBeginPrint)
{
cout << number[i];
}
}
cout << endl;
}