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

在这里插入图片描述

解法

 直观解法是逐一枚举每个数字计算每个数字的数位和直到大于输入n,然后再从该数字中找出对应的那一位。
 更快的解法是我们可以把数字序列0,1,2,3...看成由不同位数数字组成的几部分序列0~9, 10 ~ 99,100 ~ 999.....输入n所在的数字存在于某个子序列中。可以通过计算每个序列所含位数来跳过这个序列。以n为1001为例
0~9 一共10位小于1001,所以n一定在之后的序列中,可以跳过该序列 n - 10 = 991,10 ~99 有90个数字180位, 991 > 180 所以可以跳过,n = 991 - 180 = 881, 100 ~ 999 有900个数字 2700位, 881 < 2700,所以n位于3位数组成的序列中,此时881 = 270 * 3 +1,所以n位于从100开始后的270个数的第一位即370中的7。
代码如下:

class Solution {
    public int findNthDigit(int n) {
        if(n < 0) return -1;
        // 位数
        long digits = 1;
        while(true) {
            // 当前位数一共有多少位数字 
            long numbers = countOfIntegers(digits); 
            // digits * numbers 为数位数,会超过int最大值所以要用long
            if(n < numbers * digits)
                return findNthDigit(n,digits);
            n -= digits * numbers;
            digits++;
        }
    }

    // 计算m位数字一共有多少个
    private long countOfIntegers(long digits) {
        if(digits == 1) 
            return 10L;
        long result = (long)Math.pow(10,digits -1);
        return (long)(result * 9);
    }

    private int findNthDigit(int n,long digits) {
        // number为n为数所在的数字
        long number = beginNumber(digits) + n / digits;
        long indexFromRight =digits -  n % digits;
        for(int i = 1; i < indexFromRight; ++i)
            number /= 10;
        return (int)(number % 10);
    }

    private long beginNumber(long digits){
        if(digits == 1)
            return 0;
        return (long)Math.pow(10,digits-1);
    }
}
posted @ 2020-09-07 11:47  消灭猕猴桃  阅读(74)  评论(0编辑  收藏  举报