剑指Offer44—数字序列中某一位的数字

力扣

题意

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

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

即在 给定的字符序列(01234567891011...)中返回第n位的数字(下标从0开始)

解题思路

  1. 将 101112⋯ 中的每一位称为 数位 ,记为 n ;
  2. 将 10, 11, 12,⋯ 称为 数字 ,记为 num;
  3. 数字 10是一个两位数,称此数字的 位数 为 2 ,记为 digit ;
  4. 每 digit 位数的起始数字(即:1, 10, 100, ⋯),记为 start。

观察上表,可推出各 digit  下的数位数量 count 的计算公式:count=9×start×digit

根据以上分析,可将求解分为三步:

  1. 确定 n 所在 数字 的 位数 ,记为 digit;
  2. 确定 n 所在的 数字 ,记为 num ;
  3. 确定 n 是 num 中的哪一数位,并返回结果。

1. 确定所求数位的所在数字的位数

如下图所示,循环执行 n 减去 一位数、两位数、... 的 数位数量 count,直至 n≤count 时跳出。

由于 n 已经减去了一位数、两位数、...、(digit-1位数的 数位数量count ,因而此时的 n 是从起始数字 start 开始计数的。

digit, start, count = 1, 1, 9
while n > count:
    n -= count
    start *= 10 # 1, 10, 100, ...
    digit += 1  # 1,  2,  3, ...
    count = 9 * start * digit # 9, 180, 2700, ...


2. 确定所求数位所在的数字 

此时,n的范围已经在 所在数字的位数 的数位数量 的范围之中了。

如下图所示,所求数位 在从数字 start 开始的 第 [(n - 1) / digit] 个 数字 中( startstart 为第 0 个数字)。

num = start + (n - 1) // digit

例如:n=10,由于在第一步确立 所求数位的所在数的位数 的时候,n已经减去了9,所以在到达第二步的时候,n已经变成1了,n的范围 从1~180,不会超过它所在位数的 数位数量的范围。

由于(n-1)/2=0,所以所求数位在 从数字start开始的第0位中,即在数字10中。


3. 确定所求数位在 num的哪一数位

如下图所示,所求数位为数字 num 的第 (n - 1) % digit 位( 数字的首个数位为第 0 位)。

s = str(num) # 转化为 string
res = int(s[(n - 1) % digit]) # 获得 num 的 第 (n - 1) % digit 个数位,并转化为 int

 


结论:

 所求数位是 res 。 

C++实现

class Solution {
public:
    int findNthDigit(int n) 
    {
        int digit=1;    // n所在数字的 位数。初始化为1
        long start=1;   //每digit位数的起始数字(即1、10、100...),初始化为 位数为1的数字 的起始数字。
        long count=9;   //每digit位数的 数位数量。初始化为 位数为1的数字 的数位数量

        //1、确定n所在数字的 位数。
        while(n>count)  
        {
            n=n-count;
            start=start*10;          //下一位数的 起始数字。
            digit=digit+1;          //下一个位数
            count=9*start*digit;    //下一个位数的 数位数量
        }
        //2、确定所求数位 所在的数字。
        long num = start+(n-1)/digit;
        //3、确定所求数位在num的哪一位数
        string str_num = to_string(num);
        int res = str_num[(n-1)%digit]-'0';
        return res;
        
    }
};

u1s1,这种数学推导的题遇上了,如果事先没有做过,大概率凉凉了。。。。太难了。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心之所向便是光v

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值