剑指 Offer 17. 打印从1到最大的n位数

算法思路:

  1. 定义res数组存储结果,nine、count和start用于控制递归过程。
  2. 将n赋值给类变量,初始化res和num数组。
  3. start表示num中有效位数的起始位置。
  4. 调用dfs开始递归。
  5. 递归终止条件:xn,此时得到一个数字,判断是否去除前导0后加入res。如果ninen-start,出现了"9",需回溯。
  6. 遍历’0’到’9’,递归调用dfs,并修改nine和num[]。
  7. 回溯,nine减1。
  8. dfs递归结束,返回res数组。
  9. 本题考察递归和回溯,需要理解程序的递归流程。
class Solution {
    int[] res;  //存储计算结果的数组
    int nine = 0, count = 0, start, n;  //nine记录"9"的个数,count用于记录res的索引
    char[] num, loop = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};  
    
    public int[] printNumbers(int n) {
        this.n = n;  //将传入的n赋值给类变量n
        res = new int[(int)Math.pow(10, n) - 1];  //初始化res数组
        num = new char[n];   //num存储每次递归得到的数字
        start = n - 1;   //start用于标记num的有效位数的起始位置
        dfs(0);     //开始递归
        return res;
    }
    
    void dfs(int x) {    
        //递归终止条件:x == n表示已经递归到最高位
        if(x == n) {  
            //num有效位数起始位置之后的数字转为字符串并去除前导0
            String s = String.valueOf(num).substring(start);  
            //如果不等于"0",将其添加到res并递增res索引count
            if(!s.equals("0")) res[count++] = Integer.parseInt(s);  
            //如果此时nine等于最高位到start之间的位数,说明出现了"9",需回溯     
            if(n - start == nine) start--;
            return;  
        }
        
        //遍历'0'到'9',递归调用dfs
        for(char i : loop) {  
            //如果是'9',nine加1
            if(i == '9') nine++;  
            //当前位设置为i,继续递归下一位
            num[x] = i;  
            dfs(x + 1);   
        }
        
        //回溯,nine减1 
        nine--;
    }
} 

算法思路:

  1. 初始化weishu=10^n-1,计算能打印的最大数字。
  2. 初始化数组re,长度为weishu。
  3. 给re数组赋值,从1到weishu。
  4. 返回re数组。
    该算法时间复杂度为O(n),空间复杂度为O(1)。
class Solution {
    public int[] printNumbers(int n) {
        //初始化weishu,用于计算能够组成的最大数字,weishu=10^n-1
        int weishu = (int)Math.pow(10,n) - 1;   

        //初始化数组re,长度为weishu
        int[] re = new int[weishu];              

        //给re数组赋值,从1到weishu
        for (int i = 0;i < weishu; i++){  
            re[i] = i + 1;                      
        }
        //返回re数组
        return re;                              
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值