2015-08-18 49 views
-1

我試圖解決一個問題「鑑於偶數(大於2)返回兩個素數,其總和等於給定的數字。「並獲得上述錯誤。 錯誤是由於代碼複雜性很明顯。 請提出的方法來降低複雜性如何降低這種代碼的複雜性,因爲我得到錯誤:異常線程「main」 java.lang.OutOfMemoryError:Java堆空間

我的代碼是:

public ArrayList<Integer> primesum(int A) { 

     ArrayList<Integer> arr = new ArrayList<Integer>(); 
     for(int i=0;i<=A;i++) 
     { 
      //All the numbers are prime 
      arr.add(1); 
     } 
     arr.set(0,0);// 
     arr.set(1,0); 
     for(int i=2; i<=Math.sqrt(A);i++) 
     { 
      if(arr.get(i)==1) 
      for(int j=2;i*j<=A;j++) 
      { 
      arr.set(i*j,0); 
      } 
     } 

     for(int i=0;i<=Math.sqrt(A);i++) 
     { 
      if(arr.get(i)==1) 
      { 
       boolean b = checkprime((A-i)); 
       if(b) 
       { 
        arr.clear(); 
        arr.add(i); 
        arr.add(A-i); 
        break; 
       } 
      } 
     } 

     return arr; 

    } 

    private static boolean checkprime(int p) 
    { 
     boolean k =true; 

     if(p==1) 
     return false; 

     for(int i=2;i<=Math.sqrt(p);i++) 
     { 
      if(p%i==0) 
       k=false; 

     } 
     return k; 
    } 
+3

您將太多東西添加到列表中...因此出現「內存不足」錯誤。 – Jashaszun

+0

到Java添加更多的內存用'-Xmx'命令行參數的 – Andreas

+0

可能重複[什麼是一個OutOfMemoryError,如何調試和修復它(http://stackoverflow.com/questions/24510188/what-is -out-outofmemoryerror-and-how-do-i-debug-and-fix-it) – Raedwald

回答

0

第一步在你的算法中構建了一個最大爲A的所有Integer列表,該列表可能非常大。包裝類效率非常低,每個Integer需要16個字節,更不用說List需要的空間。既然你知道這個列表的大小,我建議使用int陣列代替,其代碼是這樣的:

public int[] primesum(int A) { 

    int[] arr = new int[A + 1]; 
    for (int i = 0; i <= A; i++) { 
     // All the numbers are prime 
     arr[i] = 1; 
    } 
    arr[0] = 0;// 
    arr[1] = 0; 
    for (int i = 2; i <= Math.sqrt(A); i++) { 
     if (arr[i] == 1) 
      for (int j = 2; i * j <= A; j++) { 
       arr[i * j] = 0; 
      } 
    } 

    for (int i = 0; i <= Math.sqrt(A); i++) { 
     if (arr[i] == 1) { 
      boolean b = checkprime((A - i)); 
      if (b) { 
       arr = new int[2]; 
       arr[0] = i; 
       arr[1] = A - i; 
       break; 
      } 
     } 
    } 

    return arr; 

} 

private static boolean checkprime(int p) { 
    boolean k = true; 

    if (p == 1) 
     return false; 

    for (int i = 2; i <= Math.sqrt(p); i++) { 
     if (p % i == 0) 
      k = false; 

    } 
    return k; 
} 

(它仍然有可能得到堆錯誤與A非常大的值,但這個版本他們至少會在數組聲明的時候發生。爲了進一步優化,我恐怕你需要重新考慮你的算法,不需要這個數組,儘管olambert說,你可以隨時調整你的堆空間大小適合。)

+0

轉換成數組解決了這個問題..謝謝.. :) – jain28

0

你可以增加你的Java應用程序的堆大小,這將使你耗盡內存之前處理更大的數據集。您可以在運行程序時使用-Xms-Xmx標誌來指定應用程序的堆大小。例如:

java -Xmx1G myProgram 

會運行「myProgram」,最大堆大小爲1GB。您可以通過運行得到有關您可以指定JVM參數的更多信息:

java -X 

當然,你可能會發現你需要使用,如果您需要解決的問題對於大整數,它使用較少的內存更有效的算法。

+1

你能提出任何方法來優化這個算法嗎? – jain28

0

下面的算法使用埃拉托色尼的篩中生成所有素數大於給定數量較少的,然後如果他們的總和等於給定數量,並返回有效配對檢查。這種方法免去了使用共checkPrime()的方法:

public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    int n = 120; 
    int[] chk = new int[n]; 
    chk[0]=1; 
    chk[1]=1; 
    for(int i=2;i<n;i++) { 
     if(chk[i]!=1){ 
      chk[i]=-1; 
     } 
     if(chk[i]==1) { 
      continue; 
     } else { 
      for(int j=2;j*i<n;j++){ 
       chk[j*i]=1; 
      } 
     } 
    } 
    for(int i=2;i<n/2;i++) { 
     if(chk[i]==-1) { 
      if(chk[n-i]==-1) { 
       System.out.println(i+"+"+(n-i)); 
      } 
     } 

    } 

} 

O/P

7+113 
11+109 
13+107 
17+103 
19+101 
23+97 
31+89 
37+83 
41+79 
47+73 
53+67 
59+61 

希望有所幫助。一個匹配對發現後,您可以在休息跳過循環拋出。(我還沒有完全檢查角落的情況所以可能有一些問題的代碼,但希望它得到跨想法)

相關問題