最后一道题,我一定要自己做出来,想了不到一个小时想法差不多成熟了,但是有一个小细节出问题了,这个问题我在idea上debug都没debug出来。我先讲我的题解然后再讲我这个小问题出在哪里吧。以下是我的代码:
class Solution {
public int findNthDigit(int n) {
if(n<10)return n;
int[][] area = new int[10][2];
int start =0;
int end = 9;
for(int i =2;i<=9;i++){
start=end+1;
area[i][0]=start;
end=(int)(end+9*Math.pow(10,i-1)*i);
area[i][1]=end;
}
for(int i=1;i<=9;i++){
if(n>=area[i][0] && n<=area[i][1]){
int moreArea = n-area[i][0]+1;
int moreDig = moreArea / i;
int num =(int)(moreDig + Math.pow(10, i-1)-1);
int more = moreArea % i;
if(more == 0){
return num % 10;
}else{
String numString = String.valueOf(num+1);
char numChar = numString.charAt(more-1);
return numChar - '0';
}
}
}
return -1;
}
}
我创建一个area[10][2]的数组,area[i][0]表示i位数在序列中的起始序号,area[i][1]表示i位数在序列中的终止序号,比如area[2][0]=10,area[2][1]=190,表示两位数在序列中的起始序号是10,终止序号是190,这里我是从两位数开始的,因为一位数的话直接返回自己就好了,而这个起始和终止序号怎么算呢?
我们知道1位数有10个,分别是0-9;2位数有90个,分别是10-99;3位数有900个,分别是100-999;四位数有9000个,分别是1000-9999;…………我们可以发现i位数的个数就是9乘以10的i-1次方,这样我们算序号就简单多了,比如两位数的起始序号就是1位数的终止序号加1,两位数的终止序号就是1位数的终止序号9加上90*2;我们可以发现i位数的起始序号就是i-1位数的终止序号加1,i位数的终止序号就是i-1位数的终止序号+(i位数的个数*i),这样一来就可以算出area数组,我这里最多只能算9位数的终止序号,因为n最大2的31次方,9位数的终止序号绝对够了。
然后我们就拿n去循环中和area[i][0]和area[i][1],如果n在这中间,说明n是i位数。int moreArea = n-area[i][0]+1;这个moreArea可以算出n在i位数中的第几位,int moreDig = moreArea / i;这个moreDig表示n是i位数中的第几个数字(如果刚好除净n就在第moreDig个i位数的末尾,如果有余数n出处在第moreDig+1个i位数中),int num =(int)(moreDig + Math.pow(10, i-1)-1),num就是n所在的数字(除净的情况下是,否则是num+1)。int more = moreArea % i;看看是不是除净了,有没有余数,如果除净了直接返回num%10也就是个位,如果没除净那么n就是num+1中的余数-1位,先把num+1变成string,然后取num+1的第余数-1个char,这个char-‘0’就可以获得数字了。
我出问题的那个细节就是算end的时候我是用start+i位数的个数*i,这样就导致所有的end全算错了,除了2位数以外的start也全算错了,因为两位数的start是9+1得来的所以没算错,其他start是由上一个end得来的全错了,因为算n是第几位的时候减了start所以就错了,但是两个样例分别是3和11,3是1位数我直接返回了,11是2位数我的2位数start没错,所以两个样例都过了,示例没过。
好了,剑指offer全刷完了,接下来刷Hot100题。慢慢积累,慢慢成长吧,加油!