劍指Offer對答如流系列 - 數字序列中某一位的數字

面試題44:數字序列中某一位的數字

一、題目描述

數字以0123456789101112131415…的格式序列化到一個字符序列中。在這個序列中,第5位(從0開始計數)是5,第13位是1,第19位是4,等等。請寫一個函數求任意位對應的數字。

二、問題分析

這個尋求高效的解決方法,也是尋找規律:

  1. 個位數的個數一共有10個,即0~9,共佔了10*1位數字;(特殊)
  2. 兩位數的個數一共有90個,即10~99,每個數字佔兩位,共佔了90*2位數字;
  3. ……
  4. m位數的個數一共有9*10^(m-1)個,每個數字佔m位,佔了9*10^(m-1)*m位數字。

判斷第n個對的數字是屬於幾位數,再從幾位數中進行尋找。


舉個例子:
0123456789101112131415161718192021…

我們要取第33位。

爲了更形象,我們把上面的規律抽象成比較直觀的場景:我們把實際的數字想成它們在一個個方格里面存儲。一個方格可能儲存多個數字。

首先我們要找出第33位的字符對應的數字的位數。因爲個位數的個數有10個,兩位數的個數有90個,33介於10-100之間,可以確定是兩位。

利用一個方格存儲兩位的特點:
(33-10 )/2 得出11,這個數字加上10 就得出了第33位字符對應的數字是 21
(33-10)%2 得出 我們要的字符是 對應數字的第1位 即1
在這裏插入圖片描述

三、問題解答

  public int digitAtIndex(int index) {
        if(index<0){
            return -1;
        }
        // m位數
        int m=1;
        while(true) {
            // m位數的個數
            int numbers=numbersOfIntegers(m);
            if(index<numbers*m) {
                return getDigit(index,m);
            }
            index-=numbers*m;
            m++;
        }
    }

    // 返回m位數的總個數
    private int numbersOfIntegers(int m) {
        if(m == 1) {
            return 10;
        }
        return (int) (9*Math.pow(10, m-1));
    }

    // 獲取數字
    private int getDigit(int index, int m) {
        // 對應的m位數
        int number = getFirstNumber(m)+index/m;
        // 在數字中的位置
        int indexFromRight = m - index%m;
        for(int i=1; i < indexFromRight; i++) {
            number/=10;
        }
        return number%10;
    }

    // 第一個m位數 例如第一個兩位數是10,第一個三位數是100
    private int getFirstNumber(int m) {
        if(m==1) {
            return 0;
        }
        return (int) Math.pow(10, m-1);
    }
發佈了194 篇原創文章 · 獲贊 3472 · 訪問量 53萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章