题目:
数字以 0123456789101112131415...
的格式序列化到一个字符序列中。在这个序列中,第 5 位(从 0 开始计数)是 5,第 13 位是 1,第 19 位是 4,等等。写出一个函数,求任意第 n 位对应的数字。
解题思路:
题目中的序列,存在一个规律:
即依次由一位的数字,两位的数字,三位的数字,X 位的数字,对应的数字序列从小到大,拼接而成。
第 0 至第 10 位由只有一位的数字,即 [0, 9]
组成,共 10 个数字,在序列中共占 10*1=10
位;
第 11 至第 190 位由只有两位的数字,即 [10, 99]
组成,共 90 个数字,在序列中共占 90*2=180
位;
第 191 至第 2890 由只有三位的数字,即 [100,999]
组成,共 900 个数字,在序列中共占 900*3=2700
位;
…
依次类推。
可以看到规律,对于序列的第 n 位,肯定对应只有 X 位的数字 序列中的某一个数的某一位,即 [10 x-1, 10x-1] 中的某一个数的某一位。
求出 X 之后,且 n 减去由一位数,二位数,(X - 1)
数这些数字所占的位数,剩下的即位只有 X 位的数字所占的位数,假设位 ByteX,此时就可以知道 ByteX 对应多少个只有 X 位的数字,
即 Byte / X = Y ... index
,其中 Y 位商,index 为余数,且 Y 即对应目标数在只有 X 位数中的序列位置,index 即对应具体的那一位,即 n 对应的数字。
具体的代码实现:
private static int method(int n) {
if (n < 0) {
return -1;
}
if (n < 11) {
return n - 1;
}
int Byte = n;
int X = 1;
double tmp = 10;// 只有一位的数字共占 10 位
while (Byte - tmp > 0) {
++X;
Byte -= tmp;
// 只有 X 位所有数字在序列中共占 (Math.pow(10, X) - Math.pow(10, X - 1)) * X 位
tmp = (Math.pow(10, X) - Math.pow(10, X - 1)) * X;
}
// 求出 n 对应的是几位数,假设 X 为 2,则是 n 处于两位数的序列中
// 而两位数是从 10 开始
double base = Math.pow(10, X - 1);
// 求出在两位数序列中的第 Y 个序列位,
// 比如 n = 19 时, X 位 2,即第 n 位是位于两位数的序列中,即在 101112131415... 中
// 此时 Byte 位 9,表示是 101112131415... 的第九位
// 但是不能直接求出,因此要求出第 9 位对应的序列数,即 (9/(X = 2)) 结果为 4,余 1
// 即对应 10+4 = 14 的第 1 位(第 0 位为 1,第 1 位为 4)
int Y = Byte / X;
int index = Byte % X;
double number = base + Y;
// 这一步就是求出序列数 14 的第 1 位,即用 14 / 10,使 4 处于个位,再取余即可
int result = (int) ((number / Math.pow(10, X - index - 1)) % 10);
return result;
}