【剑指offer】JZ44 数字序列中某一位的数字

1 问题

数字以 0123456789101112131415… 的格式作为一个字符序列,在这个序列中第 2 位(从下标 0 开始计算)是 2 ,第 10 位是 1 ,第 13 位是 1 ,以此类题,请你输出第 n 位对应的数字。

数据范围: 0≤n≤10 ^ 9

示例1
输入:0
返回值:0

示例2
输入:2
返回值:2

示例3
输入:10
返回值:1

示例4
输入:13
返回值:1

2 答案

自己写的,暴力法,超出时间限制

class Solution:
    def findNthDigit(self , n: int) -> int:
        s = ''
        i = 0
        while len(s) <= 10 ** 9:
            s += str(i)
            i += 1
        return int(s[n])

官方解

  1. 位数减法

我们尝试来找一下规律:

小于10的数字一位数,1~9,共9个数字,9位;
小于100的数字两位数,10~99,共90个数字,180位;
小于1000的数字三位数,100~999,共900个数字,2700位;
……
我们可以用这样的方式,不断减去减去前面位数较少的数字的那些位,锁定第n位所在的区间,即第n位是几位数。这个区间的起点值加上剩余部分除以这个区间的位数就可以定位n在哪个数字上,再通过n对位数取模可以定位是哪一位。(下标从0开始,还没有减去第一个数据0,start从1开始的,需要对n减1)

具体做法:

  • step 1:通过对每个区间起点数字的计算,按照上述规律求得该区间的位数,n不断减去它前面区间的位数,定位到属于它的区间。
  • step 2:通过除以位数定位n在哪个数字上,用字符串形式表示。
  • step 3:通过在字符串上位置对几位数取模定位目标数字。
class Solution:
    def findNthDigit(self , n: int) -> int:
        digit = 1
        start = 1
        sum = 9
        while n > sum:
            n -= sum
            start *= 10
            digit += 1
            sum = 9 * start * digit
        num = start + (n - 1) // digit
        index = (n - 1) % digit
        return int(str(num)[index])
  1. 添0补齐法

上述思路是不断减去前面部分的,我们还可以考虑给数字增加前置0,让数字都变成相同的位数。比如我们要求第15个数字,可以在一位数前增加0,使其变成00 01 02 03 04 05 06 07 08 09,这样我们要求的数字都是两位数,相当于增加了10个位,也就要求这种情况下的第25个数字,这种情况下每个数是两位数,第25个数字属于25/2=12的一部分,那究竟是1还是2呢我们可以就看25对两位数取模,结果是第1位(下标从0开始),因此第25个数字就是2,也即是原来的第15位数字是2.

  • step 1:使用循环求n是属于几位数,i从1位数开始,每次给它增加 10 ^ i 个0,即n位数往后推 10 ^ i
  • step 2:找到目标数字后,通过数字对位数求除法找到该数字,转化为字符串类型。
  • step 3:再通过对位数取模判断是哪一位数。
class Solution:
    def findNthDigit(self, n: int) -> int:
        i = 1
        while i * pow(10, i) < n:
            n += pow(10, i)   # n 的位向后推
            i += 1
        return int(str(n // i)[n % i])

https://www.nowcoder.com/share/jump/9318638301699282190521

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LouHerGetUp

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

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

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

打赏作者

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

抵扣说明:

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

余额充值