LeetCode安排硬币递归解决方案导致StackOverflowError?

时间:2018-02-25 08:52:40

标签: c# recursion runtime-error

这是一个问题:你想要以楼梯形状形成总共n个硬币,其中每个第k行必须有正好k个硬币。给予n,找到完整楼梯的总数可以形成的行。 n是一个非负整数,适合32位有符号整数的范围。

这是我下面的递归解决方案。

public class Solution {

    public int Solver(int n, int m) {
        if(n - m < m || n == 0) {
            return m;
        }
        m++;
        return Solver(n - m, m);
    }
    public int ArrangeCoins(int n) {
        return Solver(n, 0);
    }
}

这是我得到的错误:

Runtime Error Message:
Unhandled Exception:
StackOverflowException
Stack overflow in unmanaged: IP: 0x5c441d, fault addr: 0x7fff33c3b0b8
Stack overflow in unmanaged: IP: 0x7f7a0fef6bbc, fault addr: 0x7fff33c3af68

Unhandled Exception:
StackOverflowException
Stack overflow in unmanaged: IP: 0x5681fc, fault addr: 0x7fff33c3bff8
Stack overflow in unmanaged: IP: 0x5c441d, fault addr: 0x7fff33c3a478
Stack overflow in unmanaged: IP: 0x7f7a0fef6bbc, fault addr: 0x7fff33c39fe8
Stack overflow in unmanaged: IP: 0x4b1567, fault addr: 0x7fff33c3bcc0
Stack overflow in unmanaged: IP: 0x5c441d, fault addr: 0x7fff33c39698
[ERROR] FATAL UNHANDLED EXCEPTION: Nested exception detected.
Original Exception: at (wrapper managed-to-native) System.IO.MonoIO.Close (intptr,System.IO.MonoIOError&) [0x00026] in <2e7c1c96edae44d496118948ca617c11>:0
at System.IO.FileStream.Dispose (bool) [0x00037] in <2e7c1c96edae44d496118948ca617c11>:0
at System.IO.Stream.Close () [0x00002] in <2e7c1c96edae44d496118948ca617c11>:0
at System.IO.StreamWriter.Dispose (bool) [0x00045] in <2e7c1c96edae44d496118948ca617c11>:0
at System.IO.TextWriter.Dispose () [0x00002] in <2e7c1c96edae44d496118948ca617c11>:0
at __Driver__.Main (string[]) [0x00066] in __Driver__.cs:41

Nested exception:at string.FillStringChecked (string,int,string) [0x00006] in <2e7c1c96edae44d496118948ca617c11>:0
at string.Concat (string,string,string) [0x00049] in <2e7c1c96edae44d496118948ca617c11>:0
at System.Exception.ToString (bool,bool) [0x0002e] in <2e7c1c96edae44d496118948ca617c11>:0
at System.Exception.ToString () [0x00003] in <2e7c1c96edae44d496118948ca617c11>:0

Last executed input: 1957747793

我知道这个解决方案有效,因为我可以在任何其他IDE上运行它,它适用于此错误的特定输入。究竟我做错了什么?

以下证明它适用于该输入:http://rextester.com/CNJ29548

我可以使用数学来更快地解决这个问题,但我想提高我的递归技能,这似乎是一个完美的问题。帮助

1 个答案:

答案 0 :(得分:1)

&#34;我知道这个解决方案有效&#34;。我担心你可能已经使用了programmer's proof,因为&#34; 6&#34;是&#34; 2&#34 ;;和&#34; 10&#34;和11&#34;返回&#34; 3&#34;。试试这个......

    public int Solver(int coinsRemaining, int coinsOnNextRow)
    {
        if (coinsRemaining >= coinsOnNextRow)
        {
            return Solver(coinsRemaining - coinsOnNextRow, coinsOnNextRow + 1);
        }

        return coinsOnNextRow - 1;
    }
    public int ArrangeCoins(int n)
    {
        return Solver(n, 1);
    }

仍然会获得该值的堆栈溢出,但至少它正在通往正确的答案:)

我认为问题在于使用堆栈,因为您正在使用递归。这里不需要递归...只需使用while循环(这适用于您想要的输入,给出62573作为答案,是吗?):

    public int ArrangeCoins(int coinsRemaining)
    {
        int coinsOnNextRow = 1;
        while (coinsRemaining >= coinsOnNextRow)
        {
            coinsRemaining -= coinsOnNextRow;
            coinsOnNextRow++;
        }

        return coinsOnNextRow - 1;
    }