首頁  >  文章  >  當我使用 for 迴圈時出現 stackoverflow 錯誤,但如果使用 if 區塊完成相同的操作,則不會產生錯誤

當我使用 for 迴圈時出現 stackoverflow 錯誤,但如果使用 if 區塊完成相同的操作,則不會產生錯誤

王林
王林轉載
2024-02-22 13:30:15930瀏覽

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;
    }
}

解決方法

第一個解決方案使用額外的局部變數kcur,它們在堆疊上為遞歸函數的每個執行上下文分配。這意味著您的堆疊成長速度比第二個解決方案要快一些。

是的,每種語言環境都有自己的限制來管理其堆疊。它們通常也允許更改堆疊的最大大小。請參閱 for Javafor 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中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除