题目连接:数字序列中某一位的数字_牛客题霸_牛客网 (nowcoder.com)
官方题解:
import java.util.*;
public class Solution {
public int findNthDigit (int n) {
//记录n是几位数
int digit = 1;
//记录当前位数区间的起始数字:1,10,100...
long start = 1;
//记录当前区间之前总共有多少位数字
long sum = 9;
//将n定位在某个位数的区间中
while(n > sum){
n -= sum;
start *= 10;
digit++;
//该区间的总共位数
sum = 9 * start * digit;
}
//定位n在哪个数字上
String num = "" + (start + (n - 1) / digit);
//定位n在数字的哪一位上
int index = (n - 1) % digit;
return (int)(num.charAt(index)) - (int)('0');
}
}
这个问题涉及到了一个有趣的数学规律,关键在于确定给定的数字 n
落在哪个数字区间内,以及它是那个数字的哪一位。这个解法的基本思路是先确定 n
对应的是几位数的数字,然后找到具体的数字,最后确定是该数字的哪一位。下面我将详细解释这个过程:
-
确定位数区间:
-
我们知道,1位数有9个(1-9),共有9位;
-
2位数有90个(10-99),共有90*2=180位;
-
3位数有900个(100-999),共有900*3=2700位;
-
以此类推。
这个解法首先计算
n
落在这些区间中的哪一个。例如,如果n
是172,则它会落在2位数的区间,因为172超过了1位数区间的长度(9),但不超过1位数和2位数区间总长度(9+180=189)。 -
-
计算起始数字和区间长度:
-
每个区间的起始数字是1、10、100等,这些数字是以10的幂递增的。
-
区间长度可以用
9 * start * digit
计算,其中start
是区间的起始数字,digit
是当前区间的数字位数。
在上面的例子中,2位数的起始数字是10,区间长度是180。
-
-
定位具体数字:
-
当
n
被定位到某个区间后,减去前面所有区间的长度,得到的新n
就是在当前区间的索引。 -
然后,用
(n - 1) / digit
加上区间的起始数字,就可以找到具体的数字。这里n - 1
是因为索引是从0开始的。
在上面的例子中,新
n
是172 - 9 = 163,表示172是2位数区间的第163位。所以,具体数字是10 + (163 - 1) / 2 = 91
。 -
-
定位数字的具体一位:
-
最后,使用
(n - 1) % digit
确定n
是这个具体数字的哪一位。
在上面的例子中,
163 % 2 = 1
,表示172是数字91的第1位(从0开始计数),所以答案是9。 -