打印从1到最大的n位数

一、需求

  • 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。
示例 1:

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

说明:

用返回一个整数列表来代替打印
n 为正整数

二、遍历法

2.1  思路分析

  1. 题目假定了返回的是int数组,故不存在大数越界问题,那么只需要返回存储1 ~ (10^n - 1)的数组即可;

2.2  代码实现

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

2.3  复杂度分析

  • 时间复杂度为O(10^n)
  • 空间复杂度为O(1),列表作为返回结果,不计入额外空间;

三、分治算法

3.1  思路分析

  1. 规定返回类型为字符串,因为当 n 足够大时,10^n - 1超过int型的范围,故用字符串来存储从1到最大的n位数;
  2. 详解参考:https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/solution/mian-shi-ti-17-da-yin-cong-1-dao-zui-da-de-n-wei-2/

3.2  获取从0到最大n位数的排列

class Solution {
    
	char[] loop = {'0','1','2','3','4','5','6','7','8','9'};
	char[] num;
	int n;
	StringBuilder res = new StringBuilder();

	public String printNumbers(int n) {
		this.n = n;
		num = new char[n];
		dfs(0);
		res.deleteCharAt(res.length() - 1);
		return res.toString();
	}
	//该方法的作用是固定当前位
	public void dfs(int x) {
		if(x == n) {
			res.append(num).append(",");
			return;
		}
		for(char i : loop) {
			num[x] = i;
			dfs(x + 1);
		}
	}
	
    public static void main(String[] args) {
		Solution s = new Solution();
		String str = s.printNumbers(2);
		System.out.println(str);
	}
}

3.3  打印从1到最大的n位数(返回字符串)

  1. 上面的代码存在两个问题:①当n = 2时,打印00 01 02 ... 99,高位的0应该去掉;②此方法从0开始,题目要求从1开始;
  2. 解决①的方法:定义变量start来表示字符串的左边界,例如n = 2时,00 ~09时start = 1,10~99时start = 0;
  3. 那么start的变化规律是什么?现在我们来看两个示例:①n = 2时,00 ~09时start = 1,10~99时start = 0;②n = 3时,000~009时start = 2,010~099时start = 1,100~999时start = 0;
  4. 定义变量nineCount表示一个组合(比如009)中9的数量,通过示例可以发现:start = n - nineCount,也就是说当这个条件满足时,以n = 3为例,说明当前数为009,在到下一个010之前,将start--;
  5. 利用循环从高位向低位固定字符时,每固定一个高位字符,就要将nineCount回溯到固定之前的数值,因为每个高位字符之间是并列的关系;
  6. 解决问题②的方法:添加数字字符串的时候判断是否为"0",是就直接跳过。
class Solution {
    
	char[] loop = {'0','1','2','3','4','5','6','7','8','9'};
	char[] num;
	int n;
	int start;
	int nineCount = 0;
	StringBuilder res = new StringBuilder();
	
	public String printNumbers(int n) {
		this.n = n;
		start = n - 1;
		num = new char[n];
		dfs(0);
		res.deleteCharAt(res.length() - 1);
		return res.toString();
	}
	//该方法的作用是固定当前位
	public void dfs(int x) {
		if(x == n) {
			String s = String.valueOf(num).substring(start);
			if(!s.equals("0")) res.append(s+",");
			if(start == n - nineCount) start--;
			return;
		}
		for(char i : loop) {
			if(i == '9') nineCount++;
			num[x] = i;
			dfs(x + 1);
		}
		nineCount--;
	}
	
    public static void main(String[] args) {
		Solution s = new Solution();
		String str = s.printNumbers(2);
		System.out.println(str);
	}
}

3.4  打印从1到最大的n位数(返回int[])

  1. 因为题目要求是返回 int 数组,其默认不存在大数问题,但我们用大数的方法完全可以解决非大数的问题;
  2. 可以在添加数字字符串s之前,将其转换为int类型;
class Solution {
    
	char[] loop = {'0','1','2','3','4','5','6','7','8','9'};
	char[] num;
	int n;
	int start;
	int count = 0;
	int nineCount = 0;
	int[] res;
	
	public int[] printNumbers(int n) {
		this.n = n;
		start = n - 1;
		num = new char[n];
		res = new int[(int) (Math.pow(10, n) - 1)];
		dfs(0);
		return res;
	}
	//该方法的作用是固定当前位
	public void dfs(int x) {
		if(x == n) {
			String s = String.valueOf(num).substring(start);
			if(!s.equals("0")) res[count++] = Integer.parseInt(s);
			if(start == n - nineCount) start--;
			return;
		}
		for(char i : loop) {
			if(i == '9') nineCount++;
			num[x] = i;
			dfs(x + 1);
		}
		nineCount--;
	}
	
    public static void main(String[] args) {
		Solution s = new Solution();
		int[] arr = s.printNumbers(2);
		for(int i : arr) {
			System.out.println(i);
		}
	}
}

四、学习地址

作者:Krahets

链接:https://leetcode-cn.com/problems/da-yin-cong-1dao-zui-da-de-nwei-shu-lcof/solution/mian-shi-ti-17-da-yin-cong-1-dao-zui-da-de-n-wei-2/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值