剑指offer-面试题17:打印从1到最大的n位数

题目描述

输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。

示例 1:

输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]
说明: 用返回一个整数列表来代替打印 n 为正整数

方法一(暴力法)

1.解题思路

首先确定最大的n位十进制数,然后从头到尾依次添加到结果数组

2.代码实现
class Solution {
    public int[] printNumbers(int n) {
        int end=(int)Math.pow(10,n)-1;
        int[] arr=new int[end];
        for(int i=0;i<end;i++){
            arr[i]=i+1;
        }
        return arr;
    }
}
3.复杂度分析
  • 时间复杂度:循环了10n次,时间复杂度为O(10n)
  • 空间复杂度:不需要额外的空间开销,所以空间复杂度为O(1)

方法二(考虑大数问题)

1.解题思路

首先观察从1到999的变化规律,
一位数:1,2,3,……9
二位数:10,11,12……20,21,22……90,91,……,99
三位数:100,101,……200,201……,900,901,……999
假设位数为digit,开始数字为start,可以发现digit固定时,每次都是从start开始,打印完digit位结束,然后start+1,继续打印digit位,直到start为9时,所有的digit位打印完。
我们可以考虑用一个digit长度的字符数组来存放每次打印的数字,当某一位的digit打印完,就装入结果数组,由于不能习惯上我们不会写类似001这样的数字,所以每次还要去除前导0。
可以考虑用递归来实现,递归三部曲:

  1. 递归终止条件:当所有的digit位固定好,就可以加入到结果数组
  2. 从上一层递归获取什么:在上一层固定好之后,使固定位加1,直到num数组所有位都塞满
  3. 每一层递归返回什么:该递归没有返回值
2.代码实现
class Solution {
    int[] res;   
    char[] num;
    int n,id=0;
    public int[] printNumbers(int n) {
        this.n=n;
        int end=(int)Math.pow(10,n)-1;
        res=new int[end];
        for(int digit=1;digit<=n;digit++){
            for(char start='1';start<='9';start++){
                num=new char[digit];
                //确定开始位
                num[0]=start;
                dfs(1,digit);
            }
        }
        return res;
        
    }
    private void dfs(int index,int digit){
        if(index==digit){
            String s=String.valueOf(num);
            //去除前导零
            res[id++]=Integer.parseInt(s);
            return;
        }
        for(char i='0';i<='9';i++){
            //固定某一位
            num[index]=i;
            //向后递归
            dfs(index+1,digit);
        }       
    }
}
3.复杂度分析
  • 时间复杂度:需要访问1到最大的n位十进制数,所以时间复杂度为O(10n)
  • 空间复杂度:递归栈的深度为num数组的长度,而num数组最长为n,所以空间复杂度为O(n)
4.扩展

如果真正地考虑大数问题,数据类型为int和long都可能溢出,所以应该返回String类型。由于上面的实现中直接用Integer的parseInt()方法去除了前导零,如果是String类型,可以考虑设置一个标记位,当访问的当前位不是0是,标记位置为false,而标记位为false时,才开始将num字符数组转化为String数组。
代码实现:

class Solution {
	String[] res;
    char[] num;
    int n,id=0;
	public String[] printNumbers(int n) {
        this.n=n;
        res=new String[(int)Math.pow(10,n)-1];
        num=new char[n];
        for(int digit=1;digit<=n;digit++){
            for(char start='1';start<='9';start++){
                num=new char[digit];
                num[0]=start;
                dfs(1,digit);
            }
        }
        return res;
	
    }
    private void dfs(int index,int digit){
        if(index==digit){
            String s=print(num);
            res[id++]=s;
            return;
        }
        for(char i='0';i<='9';i++){
            num[index]=i;
            dfs(index+1,digit);
        }
    }
    private String print(char[] num){
        StringBuilder sb=new StringBuilder();
        int n=num.length;
        boolean flag=true;
        for(int i=0;i<n;i++){
            if(flag&&num[i]!='0'){
                flag=false;
            }
            if(!flag){
                sb.append(num[i]);
            }
        }
        return sb.toString();
    }
}

剑指offer全集入口: 请戳这里

你可能感兴趣的:(数据结构和算法,数据结构,leetcode,算法,java)