在问 · 算法题解

400. 第 N 位数字

题目描述

把正整数 1, 2, 3, ... 按顺序首尾相接,写成一个无限长的数字串 123456789101112...。

输入整数 n,返回这个数字串中第 n 个数字。位置从 1 开始数。

示例 1
输入:n = 3
输出:3

解释:前 9 位就是 1 到 9,第 3 位是 3。

示例 2
输入:n = 11
输出:0

解释:第 10、11 位来自整数 10,第 11 位是 0。

数据范围

  • 1 <= n <= 2^31 - 1

解题思路

按位数分组:1 位数 9 个共 9 位,2 位数 90 个共 180 位,d 位数 9·10^(d-1) 个共 d·9·10^(d-1) 位。先整组跳过,直到 n 落在某组内;组内每个数占 d 位,第 (n-1)//d 个数是 start + (n-1)//d,再取它的第 (n-1)%d 位。定位到组内哪个数这一步也可以用二分,但直接做除法就是一步到位的“二分”。

为什么正确

每次循环后,n 是在“所有 d 位及以上的数字串”中的位置,start 是最小的 d 位数。

复杂度分析

时间 O(log n),空间 O(log n)(转字符串)。

易错点

n 可达 2^31 - 1,d·cnt 在 d=9 时是 81 亿,超过 32 位整数,C++/Java 要用 64 位。另外 n 要先减 1 再做除法和取模,否则在每个数的最后一位上会错一位。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def findNthDigit(self, n: int) -> int:
        d, cnt, start = 1, 9, 1
        while n > d * cnt:
            n -= d * cnt
            d += 1
            cnt *= 10
            start *= 10
        num = start + (n - 1) // d
        return int(str(num)[(n - 1) % d])

载入编辑器,自己跑一遍 →

二分查找 专题的其他题目

查看 二分查找 全部题目 →