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

image.png
注意!需考虑大数

思路:

  • n位数需要输出1~10^n-1
  • 当需要考虑大数时,用int类型不能包含所有情况,因此需要用字符数组的全排列来得到。
  • 两位数需要两层for循环来得到十位和个位的排列组合,n层for循环用递归代替
  • 字符数组转换为int类型:

    字符数组--字符串(String)--int
      ----s = String.valueOf(num)----Integer.parseInt(s)
    • public static String valueOf(Object obj)
      image.png
      注意,valueOf是可以将字符Char[]数组转换成字符串的。
      这里也用到的是这个性质。
    • public String substring(int begin,int end)
    • public String substring(int begin)
    • 返回一个字符串的子串,从begin到end-1,长度为end-begin

    "hamburger".substring(4,8) 得到"urge"

  • 用递归表示多层for:具体

    void def(int n){
      if(){
         ...
         return;
      }
      for(xxx){
      
        def();核心在for循环中调用自己
      }
    }
    • 框图:

    image.png

  • 去零。全排列的结果无法避免地会出现[001,002,003...]而不是题目所需要的[1,2,3,...,999]

    • 结果中的某一个数的位数和9的个数和n的关系有:
    输入n此时的数此时该数的位数subString(start)中的start9的个数nine
    209111
    3009121
    3099212

    得到结论:

      n  = start + nine

    ,因此在满足以上条件时,需要扩大子字符串的范围,即start--

    • 计算 nine。是在for里计算的,同时 计算了09,变20时跳出个位的循环,需要nine-1,不能影响后面20的时候,nine应该是0,而不是1。

操作:

public class Solution {
    char[] arr = {'0','1','2','3','4','5','6','7','8','9'};
    int n;
    int[] res;
    char[] num;
    int nine,start, k =0;
    public int[] printNumbers(int n){
        this.n = n;
        res = new int[(int) Math.pow(10,n)-1];
        num = new char[n];
        start = n-1;
        def(0);
        return res;
    }
    public void def(int x){

        if (x == n){
            String s = String.valueOf(num).substring(start);
            if(s.equals("0")) return;
            res[k] = Integer.parseInt(s);
            k++;
            if (n-start == nine) start--;
            return;
        }
        for (char a :
                arr) {
            if (a=='9') nine++;
            num[x] = a;
            def(x+1);
        }
        nine--;
    }
}

可于d25包查看。


MeeWoW
18 声望1 粉丝

加油