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

在这里插入图片描述


逐步求解:

在这里插入图片描述

eg:n=548
对于012345678910111213.....先求出第548位对应的数所在“计数”:219;
求出第548位数字,对应“计数”的位数:219对应3位,d=3;
求出第548位数字,对应“计数”所在段的数字量:100-999共有900,count=900;
求出219是从谁开始数的:100;
求出第548位数字,对应是219的第几位,对应第1位(从第0位开始);
去掉2191位之后的数:21 (219从左到右,依次为第0 1 2):
取出21的个位:21%10=1 即可

c++


class Solution {
public:
    int findNthDigit(int n) {
        if(n<10){
            return n;
        }
        // d位的数字有count个
        long d = 1;
        long count = 9;
        /*
        第n位数字对应计数,有几位(d),计数区间(100-999)(3位数区间)总个数900(count)
        第一区间 1-9, 数字个数9,数位个数9(1x9)(每个数1位,有9个数)            
        第二区间 10-99, 数字个数90,数位个数180(2x90)(每个数2位,有90个数)           
        第三区间 100-999, 数字个数900,数位个数2700(3x900)(每个数3位,有900个数)     
        */
        // 判断在第几区间,更新所在区间位数d,区间内数字个数count,数位个数n
        while(n > d*count){// 数位个数=每个数几位*区间内数字个数,n>d*count不在此区间
            n -= d*count;  // 减去上个区间个数
            d++;           // 更新d
            count *= 10;   // 更新count
        }// 跳出时n是所在区间内,从区间开始数字开始的第n位
        // 找到第n位对应数字
        int ds = pow(10,d-1);  // 区间开始的数字(1,10,100,1000)
        int dnum = ds + (n - 1)/d;  // 此时n是该数字在该区间的第几位,整除该区间位数,得到该数字对应"计数"在区间的第几个计数,+区间开始数字,得到原始第n位对应计数
        int dth = (n - 1) % d;  // 该数字在该计数上的位置(从左到右)(每个"计数"有d位,求余)
        
        return dnum / (int)(pow(10,d - dth - 1)) % 10;
        // dnum / (10 ** (d - dth - 1)) 删去该该计数中该数字后的数字 eg219找1->先变为21
        // 再求个位:21->1: %10
    }
};

python


class Solution:
    def findNthDigit(self, n: int) -> int:
        if n < 10:
            return n
        d, count = 1, 9 # d位的数字有count个
        # 先找到n是几位数第几个, 循环结束后 n是d位数的第 (n - 1) // d 个数
        while n > d * count:
            n -= d * count
            d += 1
            count *= 10
        #print(d, count)
        ds = 10 ** (d - 1) # d位数的开始的数
        # 再确定n具体对应着哪个数
        dnum = ds + (n - 1) // d
        # 再确定n在dnum的第几位上
        dth = (n - 1) % d
        # d位数中的dnum的第dth位即为所求
        #print(ds, dnum, dth)
        return dnum // 10 ** (d - dth - 1) % 10


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值