题目来源:LeetCode 400. 第 N 位数字
问题抽象: 在无限整数序列 1,2,3,4,5,...,10,11,... 连接形成的字符串中,找到 第 n 位十进制数字(从 1 开始计数),满足以下核心需求:
-
序列特性:
- 序列由所有正整数按升序连接而成(如
"123456789101112..."); - 第
n位指从左向右数第n个字符(如n=3时字符为'3',n=10时字符为'1'(来自"10"))。
- 序列由所有正整数按升序连接而成(如
-
分组定位:
- 按数字位数分组:
- 1 位数(1-9):共
9个数字,占9位; - 2 位数(10-99):共
90个数字,占180位; - 3 位数(100-999):共
900个数字,占2700位; - 一般化:
k位数占位9×10^{k-1}×k。
- 1 位数(1-9):共
- 定位步骤:
- 确定
n所在数字的位数k(通过循环减去低位组总位数); - 计算该组内的目标数字:
num = 10^{k-1} + ⌊(n-1)/k⌋; - 提取数字的第
r位:r = (n-1) mod k(从左到右索引)。
- 确定
- 按数字位数分组:
-
边界处理:
- 最小值:
n=1返回1(序列首位); - 大数处理:
n最大为2^31-1(需高效定位,避免遍历); - 位数溢出:
k最大为10(因10^{10}已超过2^31); - 跨组处理:如
n=10位于2位数组(数字10的首位'1')。
- 最小值:
-
计算约束:
- 时间复杂度 O(log n):位数
k的循环次数为O(log₁₀ n); - 空间复杂度 O(1):仅存储位数、偏移量等常数变量;
- 输入范围:
1 ≤ n ≤ 2^31-1。
- 时间复杂度 O(log n):位数
-
特殊案例:
n=3→'3'(来自数字3);n=10→'1'(来自"10"的首位);n=11→'0'(来自"10"的末位);n=1000→'3'(来自数字370的某一位)。
输入:整数 n(正整数)
输出:第 n 位数字(整数 0-9)。
解题思路
题目要求在无限整数序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, … 中找到第 n 位数字。解题的核心是分三步定位:
-
确定数字的位数(digit):
- 不同位数的数字占据不同的位数范围:
- 1 位数:1~9,共 9 个数字,总位数 9
- 2 位数:10~99,共 90 个数字,总位数 180
- 3 位数:100~999,共 900 个数字,总位数 2700
- 以此类推
- 循环减去各范围的总位数,直到 n 落在当前位数范围内。
- 不同位数的数字占据不同的位数范围:
-
确定具体的数字(num):
- 根据剩余位数 n 和当前位数 digit,计算目标数字:
num = start + (n - 1) / digit start是当前位数范围的起始数字(如 1 位数的 1,2 位数的 10)
- 根据剩余位数 n 和当前位数 digit,计算目标数字:
-
确定数字中的具体位:
- 将数字转为字符串,通过
(n - 1) % digit定位字符位置 - 将字符转换为数字后返回
- 将数字转为字符串,通过
代码实现(Java版)🔥点击下载源码
class Solution {
public int findNthDigit(int n) {
int digit = 1; // 当前数字位数(1,2,3...)
long start = 1; // 当前位数范围的起始数字(1,10,100...)
long count = 9; // 当前位数范围内的总位数(9,180,2700...)
// 1. 确定n所在的数字位数
while (n > count) {
n -= count; // 减去已跳过的总位数
digit++; // 位数增加
start *= 10; // 起始数字扩大10倍
count = 9 * start * digit; // 计算新位数范围的总位数
}
// 2. 确定具体的数字
long num = start + (n - 1) / digit;
// 3. 确定数字中的具体位
return Long.toString(num).charAt((n - 1) % digit) - '0';
}
}
代码说明
-
变量作用:
digit:当前处理的数字位数(1位、2位等)start:当前位数范围的起始数字(1位从1开始,2位从10开始)count:当前位数范围的总位数(9、180等)
-
核心循环:
- 不断减去低位数范围的总位数,直到
n落在当前位数范围内 - 每次循环更新位数、起始数字和总位数:
- 位数
digit增加 1 - 起始数字
start扩大 10 倍 - 总位数
count = 9 × start × digit
- 位数
- 不断减去低位数范围的总位数,直到
-
定位数字:
(n - 1) / digit:计算当前位数范围内的第几个数字(从0开始)start + (n - 1) / digit:得到目标数字
-
定位具体位:
(n - 1) % digit:数字中的字符索引(0表示最高位)- 将目标数字转为字符串后取对应字符,转换为数字返回
复杂度分析:时间复杂度:O(log₁₀n),循环次数与数字位数相关。空间复杂度:O(1),仅使用常数级额外空间。
提交详情(执行用时、内存消耗)

1132

被折叠的 条评论
为什么被折叠?



