1. 题目来源
链接:数字序列中某一位的数字
来源:LeetCode——《剑指-Offer》专项
2. 题目说明
数字以 0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第 5 位(从下标 0 开始计数)是 5,第 13 位是 1,第 19 位是 4,等等。
请写一个函数,求任意第 n
位对应的数字。
示例 1:
输入:n = 3
输出:3
示例 2:
输入:n = 11
输出:0
限制:
0 <= n < 2^31
3. 题目解析
方法一:数学+思维+巧妙解法
这道题的关键就是要找出第 N
位所在的数字,然后可以把数字转为字符串,这样直接可以访问任何一位。分析自然数序列和其位数的关系:
- 前 9 个数都是 1 位
- 10 到 99 总共 90 个数字都是两位
- 100 到 999 这 900 个数都是三位的
那么这就很有规律了,可以定义个变量 cnt
,初始化为 9,然后每次循环扩大 10 倍,再用一个变量 len
记录当前循环区间数字的位数,另外再需要一个变量 start
用来记录当前循环区间的第一个数字,n
每次循环都减去 len * cnt (区间总位数)
,当 n
落到某一个确定的区间里了,那么 (n - 1) / len
就是目标数字在该区间里的坐标,加上 start
就是得到了目标数字,然后我们将目标数字 start
转为字符串,(n - 1) % len
就是所要求的目标位,考虑 int
溢出问题,就干脆把所有变量都申请为long long 了。
参见代码如下:
// 执行用时 :0 ms, 在所有 C++ 提交中击败了100.00%的用户
// 内存消耗 :8.3 MB, 在所有 C++ 提交中击败了100.00%的用户
class Solution {
public:
int findNthDigit(int n) {
long long len = 1, cnt = 9, start = 1;
while (n > len * cnt) {
n -= len * cnt;
++len;
cnt *= 10;
start *= 10;
}
start += (n - 1) / len;
string t = to_string(start);
return t[(n - 1) % len] - '0';
}
};