![](/img/trans.png)
[英]Why does my O(NLogN) algorithm to find anagrams run faster than my O(N) algorithm?
[英]Why does this O(N^2) algorithm run so quickly?
該算法為O(n 2 ),但是運行時間不到一秒鍾。 為什么這么快?
public class ScalabilityTest {
public static void main(String[] args) {
long oldTime = System.currentTimeMillis();
double[] array = new double[5000000];
for ( int i = 0; i < array.length; i++ ) {
for ( int j = 0; j < i; j++ ) {
double x = array[j] + array[i];
}
}
System.out.println( (System.currentTimeMillis()-oldTime) / 1000 );
}
}
編輯:
我將代碼修改為以下代碼,現在它運行非常緩慢。
public class ScalabilityTest {
public static void main(String[] args) {
long oldTime = System.currentTimeMillis();
double[] array = new double[100000];
int p = 2;
int m = 2;
for ( int i = 0; i < array.length; i++ ) {
p += p * 12348;
for ( int j = 0; j < i; j++ ) {
double x = array[j] + array[i];
m += m * 12381923;
}
}
System.out.println( (System.currentTimeMillis()-oldTime) / 1000 );
System.out.println( p + ", " + m );
}
}
我認為這里的問題是一切都在優化。 這是我的理由:
x
的值-數組全為0,因此x
始終取值為0。 x
未使用,可以進行優化。 您所剩下的代碼並不多,這就是為什么它可能運行得如此之快的原因!
作為參考,我在自己的計算機上嘗試了此方法,並通過將其不斷乘以10來改變陣列大小,並發現性能絕對沒有變化-它總是完成並輸出需要0秒的時間。 這與優化假設一致,該假設指出運行時間應為O(1)。
編輯 :您編輯的代碼進一步支持了我的想法,因為現在循環的主體具有副作用,因此無法進行優化。 具體來說,由於m
和p
在循環內更新,因此編譯器無法輕松優化整個循環,因此您將開始看到O(n 2 )性能。 嘗試改變數組的大小,然后觀察會發生什么。
希望這可以幫助!
算法的順序不會告訴您它運行的速度。 它告訴您當n的大小更改時其速度如何演變。
O(n)= n ^ 2表示如果嘗試使用10,000,000個元素,則需要(大約)當前時間的4倍。
因為雙循環實際上什么也沒做,所以JIT可以啟動並優化工作。
請注意,這對於Java和JVM的每個版本以及實現來說都太具體了-在我的版本上,它運行了大約一分鍾。
您可以添加一個
System.out.println(x)
如果要查看O(N ^ 2)行為,則在for循環之后和之后只是停止優化。
我認為這無關緊要.O(N ^ 2)更快,但參考了什么。 您只能說某事是快速的,只有當您將其與某事進行比較時。 是不是
此外,時間也取決於輸入大小。 嘗試較大的輸入,您會看到O(N)和O(N ^ 2)之間的差異。
為一些實用參考。 SPOJ是一個編程競賽網站,它使用兩個處理器來檢查輸入代碼中的代碼。
(Intel Pentium III 733 MHz)-包含自2004年問世以來為SPOJ服務的老式固態Pentium III機器。由於這些機器速度較慢,因此由SPOJ問題設置者創建的法官可以更輕松地測試算法的復雜性在解決方案中使用時無需創建龐大的數據集(您可以輕松分辨出它們之間的O(n)和O(nlogn)之間的差異)。
(Intel Pentium G860 3GHz)-這個新群集由現代且快速的Intel Pentium G860 CPU組成。 在此,您的提交速度將比前一個提交快30到50倍。 因此,可以預期,如果在家中測試解決方案,那么它在SPOJ上的執行時間將相似。 在此群集上,提交的內存限制為1536 MB。
更多信息:在Intel Pentium G3860 3GHZ上,通常在1秒內循環運行高達10 ^ 7。 因此您的10(^ 7)的O(N)算法僅需1秒。 現在取N = 10 ^ 7並做O(N ^ 2)並嘗試一下..您可以自己體驗時差
編譯器優化在這方面也起着重要作用! 您的代碼也太簡單了! 您的數組為空!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.