整数の累乗
トピック:数値nを入力し、1から最大のn桁までの10進数を順番に出力します。たとえば、3を入力すると、1、2、3は最大の3桁の数字999まで印刷されます。
1.
一見したところ落とし穴、それは非常に単純に見えます、それは1つのループで行うことができます
void PrintToMaxOfNDigits_1(int n)
{
int number=1;
int i=0;
while(i++<n)
number*=10;
for(i=1;i<number;++i)
print("%d\t",i);
}
しかし、よく考えてみると、nの範囲がないので、nが大きい場合は、整数(int)でも長整数(long long)でもオーバーフローします。
だから実際にはこれは大きな問題です!
多数の問題は何ですか?
もちろんそうです-ひも!
2.文字列のデジタル加算をシミュレートします。
最大数はn桁であるため、長さがn + 1の文字列が必要です(文字列の最も一般的な桁は\ 0です)。実際の数が十分でない場合n最後、文字列の前半に0を追加します。
まず、文字列の各桁を「0」に初期化します。次に、文字列で表される数値に毎回1を加算して、出力します。したがって、2つのことを行うだけで済みます。1つは文字列で表される数値にアナログを追加すること、もう1つは文字列で表される数値を出力することです。
上記の考え方によれば、次のコードがあります。
void PrintToMaxOfNDigits(int n)
{
if(n<=0)
return;
char* number=new char[n+1];
memset(number,'0',n);
number[n]='\0';
while(!Increment(number))
{
PrintNumber(number);
}
delete []number;
}
その中で、関数Incrementは、1ずつ増加した数値文字列番号を表し、関数PrintNumberは、数値を出力するためのものです。
ここで重要なのは、2つの関数を作成することです。
a。Increment関数
は、数値の1ずつの増加を停止するタイミングをどのように認識しますか。つまり、最大n桁の「9999 ... 999」に達したときに、増加するたびにstrcmp関数を呼び出して、文字列を比較します。 「9999 ... 999」が最大の数値。strcmpの呼び出しは簡単ですが、答えは、長さnの文字列の場合、複雑さはO(n)です。
もっと良い方法はありますか?もちろん、「999 ... 999」に1を加えた場合のみ、最初の文字(添え字は0)に基づいてキャリーが生成されることがわかります。このとき、これは最大のn桁の数値です。このとき、Incrementはtrueを返し、ループは停止します。
コードは次のように表示されます。
bool Increment(char* number)
{
bool isOverflow=false;
int nTakeOver=0;
int nLength=strlen(number);
for(int i=nLength-1;i>=0;i--)
{
int nSum=number[i]-'0'+nTakeOver;
if(i==nLength-1)
nSum++;
if(nSum>=10)
{
if(i==0)
isOverflow=true;
else
{
nSum-=10;
nTakeOver=1;
number[i]='0'+nSum;
}
}
else
{
number[i]='0'+nSum;
break;
}
}
return isOverflow;
}
a.PrintNumber関数
桁数が足りない場合は、数字の前に0を付けますが、印刷時には印刷しないので、最初のゼロ以外のときに印刷する必要があります。
void PrintNumber(char* number)
{
bool isBeginning=true;
int nLength=strlen(number);
for(int i=0;i<nLength;++i)
{
if(isBeginning && number[i]!='0')
isBeginning=false;
if(!isBeginning)
{
printf("%c",number[i]);
}
}
printf("\t");
}
3.再帰により、コードがより簡潔になります。
数値の前に0を追加すると、n桁のすべての10進数が、実際には0から9までの時間で完全に配置されていることがわかります。つまり、0から9までの数字の各桁を配置し、すべての10進数を取得します。印刷時に最初の0が印刷されないだけです。
完全な配置は簡単に表現できます。数字の各桁は0から9までの数字で、次の桁を設定できます。再帰的な終了条件が次の場合番号の最後の桁を設定します。
void PrintToMaxOfNDigits(int n)
{
if(n<=0)
return;
char* number=new char[n+1];
number[n]='\0';
for(int i=0;i<10;++i)
{
number[0]=i+'0';
PrintToMaxOfNDigitdRecursively(number,n,0);
}
delete[] number;
}
void PrintToMaxOfNDigitdRecursively(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';
PrintToMaxOfNDigitdRecursively(number,length,index+1);
}
}
参考書:「ソードフィンガーオファー」