题目:数字以0123456789101112131415…的格式序列化到一个字符序列中。在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。请写一个函数,求任意第n位对应的数字。
方法一:从0开始进行枚举。每枚举一个数字的时候,求出该数字是几位数,然后把该数字的位数与前面所有数字的位数进行累加。如果位数之和小于或等于n,继续枚举下一个。当大于n的时候,那么n位数字就一定在这个数字里,然后在这个数字中找出对应的一位。
方法二:找出规律,跳过某些数字。例如序列的第1001位是什么?序列前的0~9这10个数字只有1位数,直接跳过。然后在后面的序列中找第991(1001-10)位的数字。然后接下来的180位数字是10~99的两位数,因为991>180,继续跳过。在后面找811(991-180)位的数字。下来2700位是100~999的三位数,由于811<2700,所以第811是某个三位数中的一位,811=270*3+1,所以是从100开始的第270个数字即370的中间一位,也就是7。
class Solution {
public int findNthDigit(int n) {
if(n<0){
return 0;
}
//位数
int digits=1;
while(true){
//找出这个位数所拥有的数字个数
long numbers=count(digits);
//如果n在这个范围,进行查找
if(n<numbers*digits){
return digitsIndex(n,digits);
}
//否则跳过
n-=digits*numbers;
digits++;
}
}
//统计位数所拥有的数字个数
private int count(int digits){
if(digits==1){
return 10;
}
int count=(int)Math.pow(10,digits-1);
return 9*count;
}
//查找这个数
private int digitsIndex(int index,int digits){
//报错是因为超出了范围
//起始数+这个数在位于范围内的位置
long number=beginNumber(digits)+(long)index/digits;
int indexFromDigits=digits-index%digits;
for(int i=1;i<indexFromDigits;++i){
number=number/10;
}
return new Long(number%10).intValue();
}
//找到这个位数的起始数
private static long beginNumber(int digits){
if(digits==1){
return 0;
}
return (long)Math.pow(10,digits-1);
}
}
注意的是:如果给的n位数大的话,再求位数拥有的个数和起始数的时候,会因为超出int的存储范围进行错误的运算。为了保证数据的 正确性,要注意使用