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

这篇博客介绍了如何解决《剑指Offer》中的一道题目,即根据输入的数字n打印从1到最大的n位数。博主提供了两种解题思路,一种是直接使用数组暴力求解,另一种是利用字符串进行全排列递归生成。在Java代码实现中,博主展示了如何通过递归生成n位数的全排列,并过滤掉高位为0的情况,以确保生成的数字有效。这种方法在n值较大时仍能处理大数问题,避免了类型溢出。
摘要由CSDN通过智能技术生成

剑指 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位的最大数。
但是没有说明n的范围,用返回整数列表来代替打印。所以证明这道题的返回值范围不会超出int类型,可以用暴力。

法一:暴力
直接利用数组输出。
首先,计算一下这个数组的长度,就是要输出多少个数。
看示例,找规律。
n = 1 时,数组长度为 9
n = 2 时,数组长度为 99
……
所以,输入数字 n 时,输出数字的总个数为10^n^-1,然后

法二:用字符串模拟加法 / 全排列 / 递归
看评论说,这道题原题考的是大数问题。。。

参考了k神的解法。
当n比较大时,会超出 int 类型的范围。但是当n足够大时,用long什么的也完全不行,因为这些数字变量类型的取值范围都是有限的,所以,可以用字符串来表示大数。
通过观察,n 为1的时候为1-9,n为2的时候为1-99,n为3的时候为1-999.
在这里插入图片描述
所以,这其实是一个n为的,由0-9组成的全排列(高位给看做有0占位)。

全排列,就高中学那个,差点没想起来。
给n个位置,每个位置可以填0-9 这10个数,一共的可能有10n种排列

用递归生成全排列
在这里插入图片描述
同时,添加数字字符的时候,检测一下,高位是否为0,为0时跳过,不为0时输入。

时间复杂度 :O(10n)
递归的生成的排列的数量为 10n

空间复杂度 :O(10n)
结果列表的长度为 10n - 1,各数字字符串的长度区间为 1, 2, …, n 因此占用 O(10n)的额外空间。

java代码

//法一
class Solution {
    public int[] printNumbers(int n) {
        int m= (int)Math.pow(10,n);//10的n次方
        int[] a = new int[m-1];
        for(int i=0; i < m-1; i++){
            a[i] = i+1;
        }
        return a;
    }
}
//法二
class Solution {
    char[] num;
    int[] ans;
    int count = 0,n;
    public int[] printNumbers(int n) {
        this.n = n;
        num = new char[n];//定义长度为n的字符列表
        ans = new int[(int) (Math.pow(10, n) - 1)];//定义答案数组的长度
        dfs(0);//开启全排列递归
        return ans;
    }
    private void dfs(int n) {
        if (n == this.n) {//终止条件,以固定完所有位
            String tmp = String.valueOf(num);//num转化为字符串
            int curNum = Integer.parseInt(tmp);//再转化为int类型
            if (curNum!=0) {
            	ans[count++] = curNum;
            }
            return;
        }
        for (char i = '0'; i <= '9'; i++) {//遍历0-9
            num[n] = i;//固定第n位为i
            dfs(n + 1);//开启固定下一位
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寂静花开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值