php小編草莓帶您探討Java程式設計中的一個常見問題:當使用for循環時出現stackoverflow錯誤,但使用if塊卻不會產生錯誤。這種現象可能源自於for迴圈的重複呼叫導致棧溢出,而if塊則避免了這種情況。透過深入分析問題根源和Java記憶體管理機制,可以更好地理解並解決這個問題。
我正在解決 dsa 問題
我使用的語言是 java se
# 連結:https://www.codingninjas.com/studio/problems/ninja-s-training_3621003
我知道我的解決方案是正確的,但對於其中一個測試案例(我不知道測試案例是什麼,因為它不顯示測試案例),我遇到了stackoverflow 錯誤,所以我只是用一些if 語句替換了for 循環,它已修復,我想知道為什麼我首先遇到錯誤
c 中的相同解決方案(使用 for 迴圈)也沒有錯誤,java 和 c 的堆疊空間運作方式是否不同?
# 這兩種方法中的函數呼叫量保持相同,但其中一種方法給出了 stackoverflow 錯誤,這是沒有意義的。所以呼叫次數不可能超過堆疊空間,如果有人能為我解決這個問題那就太好了
這是帶有for迴圈的程式碼:
public class solution { private static int dp[][]; private static int rec(int day, int prev, int[][] points) { if (day == 0) { // no more days left. return 0; } if (dp[day][prev] != -1) { return dp[day][prev]; } // merit points of ith task on nth day. int ans = points[day - 1][prev - 1]; int mx = 0; for(int k=1;k<4;k++) { if(k!=prev) { int cur=rec(day-1, k, points); mx=math.max(cur,mx); } } dp[day][prev] = ans + mx; return ans + mx; } public static int ninjatraining(int n, int points[][]) { // dp table to memoize the solution. dp = new int[n + 1][4]; for (int i = 0; i <= n; i++) { for (int j = 0; j < 4; j++) { dp[i][j] = -1; } } int ans = 0; ans = math.max(ans, rec(n, 1, points)); ans = math.max(ans, rec(n, 2, points)); ans = math.max(ans, rec(n, 3, points)); return ans; } }
這裡是帶有 if 區塊的程式碼:
public class Solution { private static int dp[][]; private static int rec(int day, int prev, int[][] points) { if (day == 0) { // No more days left. return 0; } if (dp[day][prev] != -1) { return dp[day][prev]; } // Merit points of ith task on nth day. int ans = points[day - 1][prev - 1]; int mx = 0; if (prev == 1) { mx = Math.max(rec(day - 1, 2, points), rec(day - 1, 3, points)); } if (prev == 2) { mx = Math.max(rec(day - 1, 1, points), rec(day - 1, 3, points)); } if (prev == 3) { mx = Math.max(rec(day - 1, 1, points), rec(day - 1, 2, points)); } dp[day][prev] = ans + mx; return ans + mx; } public static int ninjaTraining(int n, int points[][]) { // DP table to memoize the solution. dp = new int[n + 1][4]; for (int i = 0; i <= n; i++) { for (int j = 0; j < 4; j++) { dp[i][j] = -1; } } int ans = 0; ans = Math.max(ans, rec(n, 1, points)); ans = Math.max(ans, rec(n, 2, points)); ans = Math.max(ans, rec(n, 3, points)); return ans; } }
第一個解決方案使用額外的局部變數k
和cur
,它們在堆疊上為遞歸函數的每個執行上下文分配。這意味著您的堆疊成長速度比第二個解決方案要快一些。
是的,每種語言環境都有自己的限制來管理其堆疊。它們通常也允許更改堆疊的最大大小。請參閱 for Java 和 for C 。
請注意,您還可以避免 if
區塊並一次處理這三種情況:
int mx = Math.max(rec(day - 1, prev % 3 + 1, points), rec(day - 1, (prev + 1) % 3 + 1, points));
如果將 points
儲存為靜態變數(就像 dp
一樣)並且不將其作為參數傳遞給遞歸函數,則可以減少更多堆疊空間。
用於取得遞迴函數結果的堆疊由於測試中可能存在很大的輸入數字 n
,因此分配給 int cur
會溢位。
https://www.php.cn/link/efc9ea3e0c2ed2c2481fe1252019266e
#以上是當我使用 for 迴圈時出現 stackoverflow 錯誤,但如果使用 if 區塊完成相同的操作,則不會產生錯誤的詳細內容。更多資訊請關注PHP中文網其他相關文章!