面试题17. 打印从1到最大的n位数

题目: 输入数字 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;
}

加油哦!🍇。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值