• 算法题:打印1到最大的n位数


    说明:本文仅供学习交流,转载请标明出处,欢迎转载!
           今天看到剑指offer上的第12题,题目例如以下:
           输入数字n。按顺序打印出从1到最大的n位十位数。

    比方输入3,则打印出1,2,3,...,999。

           当我看到这个题目的时候。第一感觉就是用递归,为什么呢?首先得从我们的一个实际数字出发,比方123。我们对数字加1,实际上分为例如以下两个步骤:
           步骤1:最低位加1;
           步骤2:若发生进位,则向更高位传播该进位的影响(这也是递归的所在)。
           在完毕这个算法题之前。我想插一句“细节决定成败!”,我们写一个程序,事实上大体的思路都能想到。而往往忽略对细节的考虑,如本题须要考虑的问题例如以下:
            1.怎样表示一个n位数?(用字符数组
            2.每次加1都在最低位进行;
            3.加1后若发生进位。则将该进位传播给高位数字(这里既可用循环,也可用递归);
            4.若最高位发生进位,则溢出,该溢出可作为打印最后一个数的标志;
            5.打印数字时,仅仅能从最高位不为0的数字起開始打印。(这符合数字的正常表示
           递归实现例如以下:
    #include<iostream>
    #include<cstring>
    using namespace std;
    bool Increment(char *str,int length)//字符串加1,假设为发生溢出,则返回true,否则返回返回false
    {
    	if(str==NULL && length<1)//假设发生溢出。则返回false
    	{
    		return false;
    	}
    	int sum=str[length-1]-'0'+1;
    	if(sum<10)//假设不发生进位
    	{
    		str[length-1]+=1;
    		return true;
    	}
    	else
    	{
    		if(length-1==0)//假设溢出,则返回false
    		{
    			return false;
    		}
    		str[length-1]='0';//发生进位,把剩下的任务交给前length-1个字符
    		return Increment(str,length-1);//递归表达式
    	}
    }
    void print(char *str)//打印字符,打印时去掉前面的几个0
    {
    	bool isBegin=false;//标识能否够開始输出
    	int i;
    	for(i=0;i<strlen(str);i++)
    	{
    		if(!isBegin && str[i]!='0')//假设找到第一个非0字符,则标识能够開始输出了
    		{
    			isBegin=true;
    		}
    		if(isBegin)
    		{
    			cout<<str[i];
    		}
    	}
    	cout<<endl;
    }
    
    void ToMaxN(int n)//打印从1到最大的N位数
    {
    	if(n>=1)
    	{
    		char *str=new char[n+1];
    		memset(str,'0',n);
    		str[n]='';
    		while(Increment(str,n))//假设能顺利增长
    		{
    			print(str);
    		}
    		delete []str;
    	}
    }
    int main()
    {
    	int n;
    	while(cin>>n)
    	{
    		if(n>=1 && n<=5)
    		{
    			ToMaxN(n);
    		}
    	}
    	return 0;
    }
            非递归实现例如以下:
    #include<iostream>
    #include<cstring>
    using namespace std;
    bool Increment(char * str)//用于将当前字符串相应的数字加1,返回true表示添加成功
    {
    	int len=strlen(str);
    	int current=str[len-1]-'0'+1;//将个位数字加1,current表示加1后的值
    	int i=len-1;//以下開始传播个位加1后的连锁进位反应
    	while(i>=0)//用i表示当前位
    	{
    		if(current<10)//若加1后不进位
    		{
    			str[i]=str[i]+1;
    			break;
    		}
    		else//假设当前位发生进位
    		{
    			if(i==0)//假设进位的是最高位。则直接发生溢出
    			{
    				return false;
    			}
    			else//假设进位的不是最高位,这里能保证i!=0,由于上面有个为0的分支处理
    			{
    				str[i]='0';//先将本位归零
    				i=i-1;//開始处理本位的上一位
    				current=str[i]-'0'+1;
    			}
    		}
    	}
    	return true;
    }
    void print(char *str)//显示该数字
    {
    	bool begin=false;
    	int i;
    	int len=strlen(str);
    	for(i=0;i<len;i++)
    	{
    		if(!begin && str[i]!='0')
    		{
    			begin=true;
    		}
    		if(begin)//假设已经找到第一个非0的高位数字
    		{
    			cout<<str[i];
    		}
    	}
    	cout<<endl;
    }
    
    void ToMaxN(int n)//client调用的函数
    {
    	char *str=new char[n+1];
    	memset(str,'0',n);//注意初值在中间,不是第三个參数
    	str[n]='';
    	while(Increment(str))
    	{
    		print(str);
    	}
    	delete []str;
    }
    int main()
    {
    	int n;
    	while(cin>>n)
    	{
    		if(n>=1 && n<=5)
    		{
    			ToMaxN(n);
    		}
    	}
    	return 0;
    }
            測试结果例如以下:
           
    參考资料:
       《剑指offer》
  • 相关阅读:
    [SUCTF 2019]EasySQL
    [强网杯 2019]随便注
    [HCTF 2018]WarmUp
    Linux下配置JDK环境
    Centos克隆虚拟机后配置网络
    Sublime安装插件
    LeetCode-91-解码方法
    LeetCode-322-零钱兑换
    LeetCode-152-乘积最大子数组
    LeetCode-139-单词拆分
  • 原文地址:https://www.cnblogs.com/jzssuanfa/p/6860557.html
Copyright © 2020-2023  润新知