leetcode-258-Add Digits
題目描述:
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