QUESTION
easy
题目描述
在无限的整数序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …中找到第 n 个数字。
示例 1:
输入: 3
输出: 3
示例 2:
输入: 11
输出: 0
说明:
第11个数字在序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... 里是0,它是10的一部分。
说明
n 是正数且在32位整形范围内(n < 2^31)
SOLUTION
忍不住看了下相关话题,给的是“数学”,那看来就是找规律了。
方法一
回到这个问题,我们把数字、第N个数、范围的大小对应起来找到他们的规律
数字 | 第N个数 | 共 |
---|---|---|
1-9 | 1-9 | 1*10^0*9 = 9 |
10-99 | 10-189 | 2*10^1*9 = 180 |
100-999 | 190-2889 | 3*10^2*9 = 2700 |
1000-9999 | 2889-38889 | 4*10^3*9 = 36000 |
… | … | … |
这样看下来,你应该发现了规律,我们只要确保 n
在对应的范围内,然后再映射到数字上就可以了,代码如下(增强了可读性,可以在很多地方提高效率)
class Solution {
public:
int findNthDigit(int n) {
int index = 0, times = 1;
long front = 1, back = 9;
while(n > back){
times++;
index++;
front = back + 1;
back += times * pow(10, index) * 9;
}
int num = pow(10, index) + (n - front) / times;
int which = times - ((n - front) % times);
int res;
while(which){
res = num % 10;
num /= 10;
which--;
}
return res;
}
};
方法二
这是另外一种实现,思路是相同的,只不过是通过不断减去 n 来控制到指定区间,然后再映射到数字上。(参考博客)
数字 | 共 | 第N个数 | 共 |
---|---|---|---|
1-9 | 9 | 1-9 | 9 |
10-99 | 90 | 10-189 | 180 |
100-999 | 900 | 190-2889 | 2700 |
1000-9999 | 9000 | 2889-38889 | 36000 |
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';
}
};