我最近在採訪中被問到如何編寫一個算法來計算給定數字中的位數。因此,舉例來說,如果我得到了一些500的結果將是3.如果我得到了一些15345的結果將是5計算一個數字中的位數 - 這兩個解決方案哪一個更快?
我想出了2個可能的解決方案:
遞歸鴻溝數值減10,直到結果小於1,然後返回我做出的遞歸計數。
將數字轉換爲字符串,然後計算此字符串中元素的數量。
然後詢問當使用非常大的數字時哪種操作更有效,我無法給出正確的答案。所以我的問題是這裏的正確答案是什麼 - 哪種算法更快,爲什麼?
我最近在採訪中被問到如何編寫一個算法來計算給定數字中的位數。因此,舉例來說,如果我得到了一些500的結果將是3.如果我得到了一些15345的結果將是5計算一個數字中的位數 - 這兩個解決方案哪一個更快?
我想出了2個可能的解決方案:
遞歸鴻溝數值減10,直到結果小於1,然後返回我做出的遞歸計數。
將數字轉換爲字符串,然後計算此字符串中元素的數量。
然後詢問當使用非常大的數字時哪種操作更有效,我無法給出正確的答案。所以我的問題是這裏的正確答案是什麼 - 哪種算法更快,爲什麼?
好了,到一個整數轉換爲字符串,基本itoa
(整數字符串)功能的工作原理有點像這樣:
result = ""
while (number > 0)
{
digit = number % 10
append digit to result
number = number/10
}
那麼,有沒有那麼多的第一和之間的差異第二個解決方案。第一種解決方案將採取O(n)迭代,其中n是整數中的位數。第二種解決方案將具有相同的複雜性,並且另外計數字符串中的Ñ位數O(n)的時間,總共O(2N) = O(n)的複雜性。
其他算法是可能的。例如,您可以查看設置的最高位,並將其與值表進行匹配。
這很大程度上取決於如何給出數字。我會解釋你給一個數字存儲爲一個機器整數。在那種情況下,我認爲最重要的是取數字的對數,這應該在不變的時間內給出答案。
你的答案都在線性時間內運行,所以它們應該被認爲是相當於 。
我不知道是什麼讓你認爲在輸入大小方面日誌不是線性的。應該閱讀,不是嗎?至於「他們應該是等同的」。常量在這樣的問題中很重要。生活並不是很大的O符號。 – amit
那麼,@amit,也是10除以不是恆定時間? –
我計時三種變體:
爲10的倍數的長度我跑10000點每個運行。
結果以微秒:
length division logarithm string length
---------------------------------------------------
10 7 10 16
20 14 14 26
30 28 14 41
40 46 14 59
50 73 14 80
60 91 14 80
70 113 14 98
80 136 14 106
90 170 14 116
100 197 14 129
有這些數據的各種來源的文物,但我覺得你的想法。
只是爲了記錄在案,這是做到這一點的最快方法,假設輸入是一個unsigned long或者int某種:
int count_digits(unsigned long n){
unsigned long long quotient;
unsigned int ctDigits = 1;
while(n > 9){
ctDigits++;
quotient = (n >> 1) + (n >> 2);
quotient += (quotient >> 4);
quotient += (quotient >> 8);
quotient += (quotient >> 16);
quotient = quotient >> 3;
n -= ((quotient << 2) + quotient) << 1; // computes the remainder
}
return ctDigits;
}
使用部門(包括任何itoa /字符串中的任何解決方案轉換)將會慢得多,因爲分割是一項昂貴的操作。在高速計算領域,這是一件壞事,壞事。
如何迭代地將數字除以10直到結果小於10? –
如果這是一個非常大的數字 - 它是如何表示的?一個'int'或甚至'long'是不夠的。什麼語言? – amit
@TedHopp是的,這是我的解決方案,但我的問題是,當我使用大數字時,我給出的兩個解決方案中的哪一個更快? – Marko