0400. 第 N 位数字
大约 4 分钟
0400. 第 N 位数字
- 标签:数学、二分查找
- 难度:中等
题目链接
题目大意
描述:给你一个整数 。
要求:在无限的整数序列 中找出并返回第 位上的数字。
说明:
- 。
示例:
- 示例 1:
输入:n = 3
输出:3
- 示例 2:
输入:n = 11
输出:0
解释:第 11 位数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是 0 ,它是 10 的一部分。
解题思路
思路 1:找规律
数字以 的格式序列化到一个字符序列中。在这个序列中,第 位(从下标 开始计数)是 ,第 位是 ,第 位是 ,等等。
根据题意中的字符串,找数学规律:
- 位数字有 个,共 位:。
- 位数字有 个,共 位:。
- 位数字有 个,共 位:。
- 位数字有 个,共 位: 。
则我们可以按照以下步骤解决这道题:
- 我们可以先找到第 位所在整数 所对应的位数 。
- 同时找到该位数 的起始整数 。
- 再计算出 所在整数 。 等于从起始数字 开始的第 个数字。即
number = start + (n - 1) // digit
。 - 然后确定 对应的是数字 中的哪一位。即 。
- 最后返回结果。
思路 1:代码
class Solution:
def findNthDigit(self, n: int) -> int:
digit = 1
start = 1
base = 9
while n > base:
n -= base
digit += 1
start *= 10
base = start * digit * 9
number = start + (n - 1) // digit
digit_idx = (n - 1) % digit
return int(str(number)[digit_idx])
思路 1:复杂度分析
- 时间复杂度:。
- 空间复杂度:。
思路 2:二分查找
假设第 位数字所在的整数是 位数,我们可以定义一个方法 用于计算所有位数不超过 的整数的所有位数和。
根据题意我们可知,所有位数不超过 的整数的所有位数和一定小于 ,并且所有不超过 的整数的所有位数和一定大于等于 。
因为所有位数不超过 的整数的所有位数和 是关于 单调递增的,所以我们可以使用二分查找的方式,确定第 位数字所在的整数的位数 。
的最大值为 ,约为 。而 位数字有 个,共 ,所以第 位所在整数的位数 最多为 位,最小为 位。即 的取值范围为 。
我们使用二分查找算法得到 之后,还可以计算出不超过 的整数的所有位数和 ,则第 位数字所在整数在所有 位数中的下标是 。
得到下标 后,可以计算出 所在整数 。 等于从起始数字 开始的第 个数字。即 number = 10 ** (digit - 1) + idx // digit
。
该整数 中第 即为第 位上的数字,将其作为答案返回即可。
思路 2:代码
class Solution:
def totalDigits(self, x):
digits = 0
digit, cnt = 1, 9
while digit <= x:
digits += digit * cnt
digit += 1
cnt *= 10
return digits
def findNthDigit(self, n: int) -> int:
left, right = 1, 9
while left < right:
mid = left + (right - left) // 2
if self.totalDigits(mid) < n:
left = mid + 1
else:
right = mid
digit = left
pre_digits = self.totalDigits(digit - 1)
idx = n - pre_digits - 1
number = 10 ** (digit - 1) + idx // digit
digit_idx = idx % digit
return int(str(number)[digit_idx])
思路 2:复杂度分析
- 时间复杂度:,位数上限 为 ,二分查找的时间复杂度为 ,每次执行的时间复杂度为 ,总的时间复杂度为 。
- 空间复杂度:。