剑指Offer_#44_数字序列中某一位的数字
Contents
题目
数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。
请写一个函数,求任意第n位对应的数字。
注意:这里的题目和测试用例不同,测试用例中数字序列是从1开始不是从0开始,所以应该从1开始来做
示例 1:
输入:n = 3
输出:3
示例 2:
输入:n = 11
输出:0
限制:
0 <= n < 2^31
思路分析
最直接的思路
从1开始遍历(枚举)正整数,访问到每个数字的时候把当前数字的位数累加到一个计数变量中,直到这个计数变量大于等于n,说明要找的第n位就在当前枚举到的数字中,然后在这个数字当中找到我们想要的那一位。
但是这样做是时间超限的。
观察规律
和上一题一样,这一题也是属于观察规律题,通过找到数学规律来代替暴力搜索,降低时间复杂度。
这一题的规律如下:
数字范围 | 位数 | 个数 | 总位数 |
---|---|---|---|
1~9 | 1 | 9 | 9 |
10~99 | 2 | 90 | 180 |
100~999 | 3 | 900 | 2700 |
从start开始 | digit | 9 * start | count = 9 *start * digit |
算法分为三步:
- 根据上述规律,循环计算每个数字范围内数字位数的
count
,n
减去count
,直到n < count
,说明要找的数就在当前范围内 - 寻找第n位数所在数字,从start开始,增加
(n-1)/digit
- 寻找第n位在数字中的位置,应该是
(n-1)%digit
解答
class Solution {
public int findNthDigit(int n) {
//题目和测试用例不符,测试用例是从1开始的
long start = 1;
long count = 9;
int digit = 1;
//1.寻找第n位所在的数字区间(即确定start,digit)
while(n > count){
n -= count;
start *= 10;
digit += 1;
count = 9*digit*start;
}
//2.定位第n位所在的数字
long num = start + (n - 1) / digit;
//3.定位第n位在数字里边的第几位
return Long.toString(num).charAt((n - 1) % digit) - '0';
}
}