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

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

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

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

示例 1:

输入:n = 3
输出:3

示例 2:

输入:n = 11
输出:0

限制:

  • 0 <= n < 2^31

做这道题强烈建议先看一下K神的做题思路以及推导过程,我是看了k神的思路然后才开始完善做题思路和代码的。毕竟这道题有点要求数学思维了。

做题思路:

这里说一下我对第二和第三步时取n-1,而非n的理解,这两步的n都从1开始,

对于第二步:这里取n-1的原因是:当n对应num中的最后一位时,不会由于进位,错误的寻找到下一个数字。

对于第三步:这里取n-1使得num中各位的位置坐标从左到右从0开始增加,即0,1,....,(digit-1),更容易理解。

另外,这里的java代码把n=0单独提出来可能更清晰一点,而且start的值应该一直小于n的值,n为int,start应该用int的范围就够了,只是count的值在第一步最后一次循环时可能会超限,应该用long。最后确定结果的时候也可以不用转为字符数组,下面是相关代码和注释:

public int findNthDigit(int n) {
        if(n==0) return 0;
        //由于是n=0时对应开始的0,这里不需要进行减操作n--;,但是如果n=1对应开始的0则需要减操作
        //排除n=0后,后面n从1开始。
        int digit = 1;
        int start = 1;
        long count = 9; //count的值有可能会超出int的范围,所以变量类型取为long
        while(n>count){//不能带=号,此时n从1开始,n=count时,属于上一个循环的最后一个数字
            n=(int)(n-count);//这里(int)不能省略
            digit++;
            start = start*10;
            count = (long)start*9*digit;
            //这里的long不能省略,否则,会先按照int类型进行计算,然后赋值给long型的count,超过int大小限制时,会出现负数
        }

        int num = start + (n-1)/digit;
        int index = (n-1)%digit;//index最大取digit-1,即此时num坐标从左到右为0,1,...,digit-1,共digit位
        while(index<(digit-1)){
        //最后的结果是num中的第index个数字,index从左到右从0开始递增,考虑到踢出右侧末尾的数字比较简单,我们从右侧开始依次踢出数字
            num = num/10;
            digit--;
        }
        return num%10;//此时num的右侧末尾数字即为结果
    }

更简洁的代码:

class Solution {
    //找规律题
    public int findNthDigit(int n) {
        int digit = 1 ; //数字位数(例如三位数digit=3)
        long start = 1; //digit位数的第一个数字
        long count = 9; //所有digit位数所占的位数
        while(n>count){//1.确定n所在的数字的位数digit
            n -= count;
            digit += 1;
            start *= 10;
            count = digit*start*9;
        }
        //2. 确定n所在的数字num
        //此时n的值是相对于start的位置
        long num = start + (n-1)/digit; //n-1是因为start是第0个数字
        //3. 确定n是num的第几位
        //这里引入s和c方便理解
        String s = Long.toString(num);
        char c = s.charAt((n-1)%digit); //n-1是因为String下标从0开始
        return c - '0';
    }
}

k神代码如下:

class Solution {
    public int findNthDigit(int n) {
        int digit = 1;
        long start = 1;
        long count = 9;
        while (n > count) { // 1.
            n -= count;
            digit += 1;
            start *= 10;
            count = digit * start * 9;
        }
        long num = start + (n - 1) / digit; // 2.
        return Long.toString(num).charAt((n - 1) % digit) - '0'; // 3.
    }
}

参考链接:

https://leetcode-cn.com/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof/solution/mian-shi-ti-44-shu-zi-xu-lie-zhong-mou-yi-wei-de-6/

posted @ 2021-09-23 17:03  RainsX  阅读(73)  评论(0编辑  收藏  举报