簡體   English   中英

遞歸java上的堆棧溢出錯誤

[英]Stack Overflow Error on recursion java

我需要找到數組中數字之間最長的方式(從大到小)。 我試圖編寫recursive函數並得到java.lang.StackOverflowError ,但由於缺乏知識,我不明白為什么會發生這種情況。

首先,我初始化數組並用隨機數填充它:

public long[] singleMap = new long[20];
for (int i = 0; i < 20; i++) {
        singleMap[i] = (short) random.nextInt(30);
    }

於是,我試圖找到掰着指頭數最長的途徑(例如{1,4,6,20,19,16,10,6,4,7,6,1 ...})並返回計數等數字。

 public int find(long[] route, int start) {
    if (route[start] > route[start + 1]) {
        find(route, start++);
    } else {
        return start;
    }
    return start;
}

所以這是日志:

 08-23 13:06:40.399 4627-4627/itea.com.testnotification I/dalvikvm:   threadid=1: stack overflow on call to    Litea/com/testnotification/MainActivity;.find:ILI
 08-23 13:06:40.399 4627-4627/itea.com.testnotification I/dalvikvm:   method requires 36+20+12=68 bytes, fp is 0x4189e318 (24 left)
 08-23 13:06:40.399 4627-4627/itea.com.testnotification I/dalvikvm:   expanding stack end (0x4189e300 to 0x4189e000)
 08-23 13:06:40.400 4627-4627/itea.com.testnotification I/dalvikvm: Shrank stack (to 0x4189e300, curFrame is 0x418a3e88)
 08-23 13:06:40.400 4627-4627/itea.com.testnotification D/AndroidRuntime: Shutting down VM
 08-23 13:06:40.400 4627-4627/itea.com.testnotification W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41a8ed40)
 08-23 13:06:40.414 4627-4627/itea.com.testnotification E/AndroidRuntime: FATAL EXCEPTION: main
                                                                         Process: itea.com.testnotification, PID: 4627
                                                                     java.lang.StackOverflowError
                                                                         at itea.com.testnotification.MainActivity.find(MainActivity.java:46)
                                                                         at itea.com.testnotification.MainActivity.find(MainActivity.java:46)

我感謝任何解釋,因為所有相關問題都沒有幫助我。 如果我的功能有問題,請更正或解釋。

編輯

我忘記說了,我用for從每個“點”的檢查方式最長

  for (int i = 0; i < singleMap.length - 1; i++) {
        int x = find(singleMap, i);
        System.out.println("steps = " + x);
    }

首先是改變

find(route, start++)

find(route, start+1)

因為post-increment返回變量的原始值,所以遞歸永遠不會前進,導致StackOverflowError

您還應該添加一個停止條件,否則您的下一個異常將是ArrayIndexOutOfBoundsException

正如Kevin評論的那樣,你也應該對find(route, start++);返回的值做一些事情find(route, start++); 否則完全無需調用它。

除了這些問題,你的邏輯是錯誤的。 該方法將返回從數組開頭開始的降序序列的最后一個索引,它不會告訴您最長的降序序列。 例如,對於{ 1, 4, 6, 20, 19, 16, 10, 6, 4, 7, 6, 1 ...}您的方法將返回0 (數組的第一個索引),因為route[0] > route[1]是假的。

您需要保留到目前為止的當前最大值,以及當前值。 所以改變如下:

public int find(int[] route, int start, int max, int currentMax) {
    if (currentMax > max) {
        max = currentMax;
    }
    if (start == route.length - 1) {
        return max;
    }
    if (route[start] > route[start + 1]) {
        return find(route, start + 1, max, currentMax + 1);
    }
    return find(route, start + 1, max, 1);
}

並用一個開始調用它

find(route, 0, 1, 0);

第二種方法是在沒有遞歸的情況下重寫它:

public int find(int[] route) {
    int max = 1;
    int currentMax = 1;
    for (int i = 0; i < route.length - 1; i++) {
        if (route[i] > route[i + 1]) {
            currentMax++;    // If next element is lower increment currentMax
            if (currentMax > max) {
                max = currentMax;   // If currentMax is the new max update max
            }

        } else {
            currentMax = 1;   // If next element is not lower restart from 1
        }
    }
    return max;
}

並稱之為

find(route);

當你調用start ++時,你會執行一個postincrementation 這意味着將參數傳遞給方法之后進行操作 - 這意味着您的方法只是在第一個參數的圓圈中繼續運行,直到內存耗盡。 用start + 1替換它,你將獲得全新的一系列例外以獲得樂趣;)

您在此算法中遇到了其他用戶指出的幾個問題。 但主要問題是該算法不能遞歸。 遞歸地,您只能找到從零索引開始的降序序列的長度。

正確的算法必須貫穿整個數組:

public static int find(long[] route) {
    int maxIdx = 0;
    int maxCount = 1;
    for (int i = 1, c = 0; i < route.length; i++) {
        if (route[i] < route[i - 1]) {
            if (++c >= maxCount) {
                maxCount = c;
                maxIdx = i - c;
            }
        } else {
            c = 0;
        }
    }
    return route.length == 0 ? -1 : maxIdx;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM