1. 程式人生 > >leetcode-258-Add Digits

leetcode-258-Add Digits

process 復雜度 lee etc 原本 原來 方法 比較 AD

題目描述:

Given a non-negative integer num, repeatedly add all its digits until the result has only one digit.

For example:

Given num = 38, the process is like: 3 + 8 = 11, 1 + 1 = 2. Since 2 has only one digit, return it.

Follow up:
Could you do it without any loop/recursion in O(1) runtime?

要完成的函數:

int addDigits(int num)

說明:

1、暴力解法如下,應該不難看懂:

    int addDigits(int num) 
    {
        int result;
        while(!(num>=0&&num<=9))//不是單位數的情況就進入處理
        {
            result=0;
            while(num!=0)//得到新的num
            {
                result+=num%10;
                num/=10;
            }
            num=result;
        }
        
return num; }

2、這道題目比較有意思的是,挑戰能不能用O(1)的時間復雜度,也就是不用循環和遞歸的方法求得輸出結果。

上述代碼中,外層循環是用來不斷地處理數的。不讓用循環,也就意味著我們必須要從數學上尋求規律。

看一下筆者舉的下述例子:

原數 0 1 2 3 4 5 6 7 8 9
對應的數 0 1 2 3 4 5 6 7 8 9
原數 10 11 12 13 14 15 16 17 18 19
對應的數 1 2 3 4 5 6 7 8 9 10/1
原數 20 21 22 23 24 25 26 27 28 29
對應的數 2 3 4 5 6 7
8 9 10/1 11/2

上述從1到9為一個循環,那麽是不是後續的數字也會遵循這樣的規律,從而最終得到在[1,9]之間的結果呢?

答案是肯定的。

因為我們假設一個比較大的兩位數,比如ab,其實ab的值是a*10+b,那麽對應的數應該是a+b。因為a和b都是正數,那麽肯定對應之後的數要小於原來的數。除非a=0,那這時候由上述表格中第一行看得很清楚。

這樣子每一個對應的數都小於原來的數,減小了9*a,那麽不斷地往前騰挪,最終必然到達[1,9]之間。

那麽我們由上述表格可以很直觀地得到一個結論:

假設要處理的數為n,則最終對應的數=(num-1)%9+1

原本我們可以直接num%9,但是對於num=9或者num=18這些9的整倍數,結論不符合,略微修改一下。

代碼如下:

    int addDigits(int num) 
    {
        return 1 + (num - 1) % 9;
    }

PS:覺得有點奇怪,2中O(1)的做法實測8ms,1中循環叠代的做法實測7ms,竟然O(1)花費時間更長……

   有同學知道原因麽?

leetcode-258-Add Digits