剑指offer打印从1到最大的n位数

题目描述

输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999
//Math.pow(double d1,double d2)注意强制转换为int
int count = (int)Math.pow(10,n);

不推荐,不是大数问题。

class Solution {
    public int[] printNumbers(int n) {
        int count = (int)Math.pow(10,n);
        int[] ans = new int[count-1];
        for(int i=0;i<count-1;i++){
            ans[i] = i+1;
        }
        return ans;

    }
}

这道题本意是大数问题,大数问题要用String类型来解决。

观察可知,生成的列表实际上是 n 位 0 - 9 的 全排列 ,因此可避开进位操作,通过递归生成数字的 String 列表。

class Solution {
    StringBuilder res;
    int count = 0, 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 的字符列表
        dfs(0); // 开启全排列递归
        res.deleteCharAt(res.length() - 1); // 删除最后多余的逗号
        return res.toString(); // 转化为字符串并返回
    }
    void dfs(int x) {
        if(x == n) { // 终止条件:已固定完所有位
            res.append(String.valueOf(num) + ","); // 拼接 num 并添加至 res 尾部,使用逗号隔开
            return;
        }
        for(char i : loop) { // 遍历 ‘0‘ - ’9‘
            num[x] = i; // 固定第 x 位为 i
            dfs(x + 1); // 开启固定第 x + 1 位
        }
    }
}

输出结果如下

输入:n = 1
输出:"0,1,2,3,4,5,6,7,8,9"

输入:n = 2
输出:"00,01,02,...,10,11,12,...,97,98,99"

输入:n = 3
输出:"000,001,002,...,100,101,102,...,997,998,999"

1.需要去除开头多余0。

1.可以采用 Integer.parseInt();
2.可以通过一个 start标识位来判断需要去除0的个数,看下面代码说明。

2.从1开始输出。

只需要判断是不是为0,即可。

class Solution {
    StringBuilder res;
    int nine = 0, count = 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-1,代表要去除前n-1个0,类似001,002,003,004需要去除前面的0.
        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);
            if(!s.equals("0")) res.append(s + ",");
            //类似99,999,等这种,说明进入了3位数和4位数,所以start要-1;
            if(n - start == nine) start--;
            return;
        }
        for(char i : loop) {
        	//判断有几个nine值,类似99,999等。
            if(i == '9') nine++;
            num[x] = i;
            dfs(x + 1);
        }
        //回溯算法要进行nine--;
        nine--;
    }
}

转换为int[],且利用Integer.parseint();

class Solution {
    char[] num;
    int[] ans;
    int count = 0,n;
    public int[] printNumbers(int n) {
        this.n = n;
        num = new char[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);
            int curNum = Integer.parseInt(tmp);
            if (curNum!=0) ans[count++] = curNum;
            return;
        }
        for (char i = '0'; i <= '9'; i++) {
            num[n] = i;
            dfs(n + 1);
        }
    }
}

另一种思想

1.当num的下标index是0时,则loop从下标1开始进行全排列
2. 当num的下标index非0时,则loop从下标0开始进行全排列

public class Solution {
    char[] num, loop = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    StringBuilder sb = new StringBuilder();
    public String printNumber(int len){
        num = new char[len];
        for(int i = 1;i<=len;i++){
            dfs(0,i);
        }
        return sb.deleteCharAt(sb.length()-1).toString();
    }
    public void dfs(int index,int len){
        if(index == len){
            sb.append(new String(num)+",");
            return;
        }
        int start = 0;
        //若从0作为起点:if(index == 0 && len>1)
        //若从1作为起点
        if(index == 0){
            start = 1;
        }else{
            start = 0;
        }
        for(int i=start;i<10;i++){
            num[index] = loop[i];
            dfs(index+1,len);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值