【JZ-17】打印从1到最大的n位数(数学)

题目

在这里插入图片描述参考

方法一-不考虑大数问题的简单解法

最大的 n 位数为 1 0 n − 1 10^n-1 10n1

class Solution {
    public int[] printNumbers(int n) {
        int end = (int)Math.pow(10, n) - 1;
        int[] res = new int[end];//创建整数列表
        //填充结果列表
        for(int i = 0; i < end; i++){
            res[i] = i + 1;
        }
        return res;
    }
}
  • 时间复杂度: O ( 1 0 n ) O(10^n) O(10n)
  • 空间复杂度: O ( 1 ) O(1) O(1)(列表作为返回结果,不计入额外空间)

方法二-考虑大数越界情况的打印

需要解决以下几个问题:

a. 大数的变量类型选择

数字的取值范围始终受限,因此选择用字符串String类型

b. 字符串集的生成

原本使用 int 类型时结果列表中的数字是递增的,每轮加1即可,现在使用String类型,通过进位操作效率较低,例如"999"到"1000"需要从个位到百位循环判断,进位3次。
我们可以借助分治算法的思想,递归生成 n 位 0~9 的全排列。例如 n = 3 时,可以先固定百位为 0~9,按顺序依次开启十位的递归,最后再固定个位。

c. 删除高位多余的0

例如 00, 01, 02,…,应该显示为 0, 1, 2,…
我们可以定义一个变量 s t a r t start start规定字符串的左边界,例如n = 2时,添加的数字字符串为 num[start: ],那么当数字为1~9时令 s t a r t = 1 start=1 start=1 ,当数字为10~99时令 s t a r t = 0 start=0 start=0
左边界的变化规律:例如 n = 3 时,在"009"到"010"、"099"到"100"时需要将左边界减1,分别是从2减到1、从1减到0。设数字各位中 9 的数量为 n i n e nine nine ,各位均为9时: n − s t a r t = n i n e n-start=nine nstart=nine
统计 n i n e nine nine :固定第 x x x 位时,当 i = 9 i=9 i=9时将 n i n e nine nine加1,回溯前恢复(即减1)。

d. 跳过0

在C.的基础上跳过一开始的0,列表直接从1开始

class Solution {
    StringBuilder res;
    int nine = 0, start, n;
    char[] num, loop = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    public String printNumbers(int n) {
        this.n = n;
        res = new StringBuilder();//字符串集
        num = new char[n];//长度为n的字符列表
        start = n - 1;//左边界初始化
        dfs(0);//全排列递归
        res.deleteCharAt(res.length() - 1);//删除最后多余的逗号
        return res.toString();
    }
    void dfs(int x){       
        if(x == n){//已固定完所有位,迭代终止
            String s = String.valueOf(num).substring(start);//用删除了高位多余的0后的字符列表创建字符串
            if(!s.equals("0"))res.append(s + ",");//将非"0"的数字字符串添加到res尾部,并用逗号隔开
            if(n - start == nine)start--;//规定字符串的左边界
            return;
        }
        for(char i : loop){
            if(i == '9')nine++;//统计数字各位中9的数量
            num[x] = i;//固定第x位
            dfs(x + 1);//开启后一位的递归
        }
        nine--;//回溯前恢复9的数量
    }
}
  • 时间复杂度: O ( 1 0 n ) O(10^n) O(10n)
  • 空间复杂度: O ( 1 0 n ) O(10^n) O(10n),这里返回的是长字符串,额外使用的结果列表 res 长度为 1 0 n − 1 10^n-1 10n1,,各数字字符串的长度区间为1, 2, …, n,故占用了 O ( 1 0 n ) O(10^n) O(10n)的额外空间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值