1. 程式人生 > >演算法作業第八週(leetcode)——440.K-th Smallest in Lexicographical Order

演算法作業第八週(leetcode)——440.K-th Smallest in Lexicographical Order

感覺這道題又是一道數學題。。。下面給出題目地址:

這題的大意是說給出一個正整數n和一個正整數k,找出1~n中按字典序排第k個的數。看上去似乎很簡單,但實際上還是要經過一番思考的。

解決這道題最簡單的想法就是一位一位的找,先判斷第一位是幾,如果第一位是2,k就必須大於第一位為1的所有數的個數,但小於等於第一位為1或2的所有數的個數。如果是3,k就必須大於第一位為1或2的所有數的個數,但小於等於第一位為1或2或3的所有數的個數。如果個數剛好相等,我們就找到了這個數並返回。

這裡我就建立了一個函式,它的作用是判斷在1~n範圍中以一個數為字首的數的個數,比如n=35時,以1為字首的數有1,10-19,所以有11個,以3為字首的有3,30-35,有7個,以25為字首的有1個。

寫完後遇到的一個比較嚴重的問題就是int的溢位,會overflow的地方我已經在程式碼中標明出來,並且改變了寫法。

下面給出實現程式碼:

class Solution {
public:
    int findKthNumber(int n, int k) {
        int temp,i, temp2, num;
        temp = 0;
        while(1)
        {
            for(i=0;i<10;i++)
            {
                if(i==0&&temp==0)
                    continue;
                temp2 = temp * 10 + i;
                num = getValue(n,temp2);
                if(num<k)
                {
                    k-=num;
                }
                else
                {
                    temp = temp2;
                    k--;
                    if(k==0)
                        return temp;
                    break;
                }
            }
        }
        return temp;
    }

    int getValue(int n, int temp)
    {
        if(n<temp)
            return 0;
        long long temp2 = temp;//overflow
        int cnt = 0;
        while(temp2<=n)
        {
            cnt += (temp2/temp)/10;//overflow cnt += temp2/(temp*10)
            temp2*=10;
        }
        temp2/=10;
        return cnt+min(n-temp2+1,temp2/temp);
    }
};

執行結果: