剑指Offer 43 44

288 阅读1分钟

这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战

剑指 Offer 43. 1~n 整数中 1 出现的次数

题目

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。

例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。

示例 1:

输入:n = 12
输出:5

示例 2:

输入:n = 13
输出:6

限制:

  • 1 <= n < 2^31

方法一

计数问题:假设给定的数为abcdefg

  • 当枚举到c时,

  • 如果c=0

    • c前面,我们可以选择的范围是0~ab-1,c后面可以选择的范围是0~9999
  • 如果c=1

    • c前面,可以选择的范围是0~ab-1,c后面可以选择的范围是0~9999;c前面还可以选择ab,后面选择的范围是0~defg
  • 如果c>1,前面可以选择的范围是0~ab,后面范围是0~9999

根据上述规律,枚举每一位即可;

class Solution {
    public int countDigitOne(int n) {
​
        List<Integer> num = new ArrayList<>();
        while(n != 0) {
            num.add(n % 10);
            n /= 10;
        }
        Collections.sort(num, (a, b)->{
            return -1;
        });
        
        if (num.size() == 1) return 1;
        
        int pre = 0, res = 0;
        for (int i = 0; i < num.size(); i ++ ) {
            int cur = num.get(i);
            if (cur == 0) {
                res += pre * Math.pow(10, num.size() - i - 1);
                pre = pre * 10 + cur;
            }
            else if (cur == 1) {
                int cnt = 0;
                int j = i + 1;
                while(j < num.size()) cnt = cnt * 10 + num.get(j ++);
                res += pre * Math.pow(10, num.size() - i - 1) + cnt + 1;
                pre = pre * 10 + cur;
            }else {
                res += (pre + 1) * Math.pow(10, num.size() - i - 1);
                pre = pre * 10 + cur;
            }
        }
        return res;
    }
}

剑指 Offer 44. 数字序列中某一位的数字

题目

数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。

请写一个函数,求任意第n位对应的数字。

示例 1:

输入:n = 3
输出:3

示例 2:

输入:n = 11
输出:0

限制:

  • 0 <= n < 2^31

方法一

数位分析:

  • 找出第n个是几位数

    • 每次将n减去所有长度为digit位数的长度,直到不够减
  • 找出第n个是在digit位数里的第几个数,即(n - 1) / digit

  • 找出第n位是在digit位数里的第几个数字,即(n - 1) % digit

class Solution {
    public int findNthDigit(int n) {
        long digit = 1, start = 1, count = 9;
        while(n > count) {
            n -= count;
            digit += 1;
            start *= 10;
            count = 9 * digit * start;
        }
        long num = start + (n - 1) / digit;
        String number = String.valueOf(num);
        char[] res = number.toCharArray();
        return res[(int)((n - 1) % digit)] - '0';
    }
}