题目: 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
1、判断位数,循环输出。
这个办法的缺陷就是不能解决大数问题,就是如果n很大的,超出了整型范围,那么程序就会崩掉,所以在不考虑大数情况下可以使用。
代码1:
//判断位数
bool isn(int i,int n)
{
int count=1;
while(i/10)
{
i=i/10;
count++;
}
if(count<=n)
{
return true;
}
return false;
}
vector<int> printNumbers1(int n)
{
vector<int> result;
int i=1;
while(1)
{
if(isn(i,n))
{
result.push_back(i);
i++;
}
else
break;
}
return result;
}
int main()
{
vector<int> result;
result=printNumbers1(3);
for(int i=0;i<result.size();i++)
{
cout<<result[i]<<" ";
}
}
2、使用字符数组来保存数字,模拟数字的加法,从而实现自加。
- 定义n+1大小的数组,0~n初始化‘0’表示数字,n+1初始化‘/0’,字符串最后一位。这样做目的是统一数值,每次从数组取值时减‘0’得到真正的数值,存储时加上‘0’.
- 数组下标从0开始,所以每次从n-1开始计算,数字存储的方式是:例如n=2,为01,02,03,所以从后面开始,所以从个位开始时不用考虑进位,直接在原来的基础上+1即可。
- 没有进位表示一个这个数字存储完毕,直接break退出循环,进行下一次。存在进位表示没完,如09+1,这时各位我们需要把n-1处理为0,进位为1,n-2处理为1.
- 如果当i==0时进位,表示最高位已经溢出,这时结束。
- 定义个字符串,保存数组元素,最后转换为数字,存储到数组中。
我们画个图举例:
代码2:
vector<int> a;
bool isover(char* num,int n)
{
int carry=0;//进位
bool over=false;//判断是否溢出
//从数组的第n-1位开始循环存储,因为数组下标从0开始
for(int i=n-1;i>=0;i--)
{
int temp=num[i]+carry-'0';//当前的数值
if(i==n-1)//第n位存储时,不会存在进位,所以直接加
{
temp++;
}
if(temp>=10)//产生进位,不会退出,会循环填充第n-1,n-2位
{
if(i==0)//表示最高位进位,则溢出
{
over=true;
}
else//不是最高位
{
carry=1;//产生进位
num[i]=temp-10+'0';
}
}
else//没有产生进位
{
num[i]=temp+'0';//把temp放进去
break;//退出循环,表示这一次做完了
}
}
return over;
}
void printn(char* num,int n)
{
string s="";//保存字符数组中的字符
for(int i=0;i<n;i++)
{
s+=num[i];//不需要考虑01问题,因为转换为十进制为1
}
int res=stoi(s);//将n进制的字符串转化为十进制
a.push_back(res);
}
vector<int> printNumbers(int n)
{
char *num=new char[n+1];//开辟数组
memset(num,'0',n);
num[n+1]='\0';
while(!isover(num,n))
{
printn(num,n);
}
return a;
}
int main()
{
vector<int> result;
result=printNumbers(3);
for(int i=0;i<result.size();i++)
{
cout<<result[i]<<" ";
}
}
3、排列组合法
就是n个位置,每个位置的取值为0~9,所以递归的让n个位置取值,通过循环,我们可以得到不同的组合。
- n位数就开辟n+1空间,给这n个位置上填充0~9即可,for控制0~9,通过递归到达下一个位置,
- ==n,表示最后一位已经填充退出递归,进行存储。
- 不能理解为[0,1,2,3,4,5,6,7,8,9]这10个数字的全排列,假如n为3,应该是_ _ _这3个位置上的取值排列,所以我们递归控制的是位置,循环控制的是取值。不同于全排列的解法:它是递归控制元素,通过下标进行位置交换。
我们同样以n=2举例子:
代码3:
vector<int>a;//必须设定为全局的,如果是局部的那么每次压栈都会把以前的清空
void printn(char* num,int n)
{
string s="";//保存字符数组中的字符
bool F=true;
for(int i=0;i<n;i++)
{
s+=num[i];
}
int res=stoi(s);
if(res!=0)//因为是0~9数字的全排列,所以存在000,判断一下
{
a.push_back(res);
}
}
//递归对每个位置进行0~9的排列
void Put(char* num,int n,int index)
{
if(index == n)//最后一位已经被设置了,跳出
{
printn(num,n);//存储结果
return;
}
else
{
for(int i=0;i<10;i++)
{
//设置数值
num[index]=i+'0';
Put(num,n,index+1);//递归给下一个进行设置
}
}
}
vector<int> printNumbers(int n)
{
if(n<=0) return a;
char* num=new char[n+1];
memset(num,'0',n);
num[n+1]='\0';
for(int i = 0;i < 10;i++)
{
num[0]=i+'0';
Put(num,n,1);//开始设置每一位的值
}
return a;
}
加油哦!🍇。