【剑指offer】17. 打印从1到最大的n位数

111 阅读1分钟

题目描述

在这里插入图片描述

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

题解

// 直接法(不推荐,毫无意义)

// 力扣
// 执行用时:1 ms, 在所有 Java 提交中击败了100.00%的用户
// 内存消耗:46.3 MB, 在所有 Java 提交中击败了90.56%的用户
class Solution {
	public int[] printNumber(int n) {
		int end = (int) Math.pow(10, n) - 1;
		int[] res = new int[end + 1];
		for (int i = 0; i < end; i++) {
			res[i] = i + 1;
		}
		return res;
	}
}

//////////////////////////// 打印形式 ////////////////////////////

class Solution {
    public static void printNumbers(int n) {
        StringBuilder str = new StringBuilder();
        // 初始化,n为多少就拓展为n位的0
        // 如n=3,则str为'000'
        for (int i = 0; i < n; i++) {
            str.append('0');
        }
        while (!addOne(str)) {  // 如果+1之后没有进位
            int index = 0;  // index初始化为0
            // index从左到右(高位到低位)遍历str的每一位字符,直到不为0的字符值
            // 如果index超过str长度边界(不可能,所以这句可以不要),则跳出while
            // 或如果index遍历的str字符不为0,则跳出while(主要用这句控制)
            while (index < str.length() && str.charAt(index) == '0') {
                index++;
            }
            // 打印str,index的位置为str不为0的位置
            // substring(index)会保留str在index位置以后的字符
            // 所以就能够保证非n位数前面的0被去除,比如原来是02,只打印2
            System.out.println(str.toString().substring(index));
        }
    }

    // 执行+1操作的函数,返回进位标识符,
    // 如果+1进位,返回true,否则返回false
    public static boolean addOne(StringBuilder str) {
        // 进位标识符,进位true,不进位false
        boolean isOverflow = false;
        // 从字符串str右边开始往左遍历,即从低位往高位遍历
        // 当前遍历位索引记为i
        // 1:如果第i位字符的值+1之后不进位,则循环结束,函数返回false
        // 2:如果第i位字符的值+1之后进位,则i左移,循环会遍历str高位,令高位执行+1操作。
        for (int i = str.length() - 1; i >= 0; i--) {
            char s = (char) (str.charAt(i) + 1);  // 第i位字符值+1,记为字符s
            if (s > '9') {  // 如果第i为字符值+1之后大于9,需要进位
                str.replace(i, i + 1, "0");  // 进位后,str中第i位设为0
                if (i == 0)
                    isOverflow = true;  // 此时将进位符isOverflow设为true,表示需要进位
            }  // 进位后,for循环会继续遍历str的高位,将高位的字符值+1,完成进位
            else {  // 如果s <= '9'
                // 不进位,将第i位的字符值替换为已经+1的s
                str.replace(i, i + 1, String.valueOf(s));
                break;  // 终止当前for循环(也就是不继续遍历字符串str的高位)
            }
        }
        return isOverflow;  // 函数结束时返回进位标识符
    }
}

///////////////////////////// 数组形式  ////////////////////////////

// 执行用时:20 ms, 在所有 Java 提交中击败了5.02%的用户
// 内存消耗:46.2 MB, 在所有 Java 提交中击败了93.47%的用户
class Solution {
	int[] res;
    int i = 0;

	public int[] printNumbers(int n) {
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < n; i++) {
            str.append('0');
        }
		res = new int[(int) Math.pow(10, n) - 1];
        while (!addOne(str)) {
            int index = 0;
            while (index < str.length() && str.charAt(index) == '0') {
                index++;
            }
			// Integer.parseInt将StringBuilder中的字符串转为整数
            res[i] = Integer.parseInt(str.substring(index));
            i++;
        }
		return res;
    }

    public boolean addOne(StringBuilder str) {
        boolean isOverflow = false;
        for (int i = str.length() - 1; i >= 0; i--) {
            char s = (char) (str.charAt(i) + 1);
            if (s > '9') { 
                str.replace(i, i + 1, "0"); 
                if (i == 0)
                    isOverflow = true;  
            }  
            else { 
                str.replace(i, i + 1, String.valueOf(s));
                break;  
            }
        }
        return isOverflow; 
    }
}