最后一道題,我一定要自己做出來,想了不到一個小時想法差不多成熟了,但是有一個小細節出問題了,這個問題我在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題。慢慢積累,慢慢成長吧,加油!