递归到正常循环转换

时间:2017-01-09 22:18:35

标签: java recursion

我有一个实际计算someValues的方法。方法如下。

public static double sum(int z, int x, int y)
    {
        double count = 0.0;
        if (x == 0)
        {
            if (z <= 0) return 1.0;
            return 0.0;
        }
        for (int i = 1; i <= y; i++)
        {
            count += sum(z - i, x - 1, y);
        }
        return count;
    }

我只想将此方法从递归转换为正常迭代。或者如果可能的话,可以使用某个线方程请帮帮我。

2 个答案:

答案 0 :(得分:1)

所以这不漂亮,但它没有递归工作。此外,由于原因,我将返回类型从double更改为int:

public static int sum(int z, int x, int y)
{
    // Compute number of calls
    int[][] calls = new int[x+1][x*y+1];
    calls[0][0] = 1;
    for (int i = 0; i < x; i++) {
        for (int j = 0; j <= x*y; j++) {
            for (int target = j+1; target <= j+y && target <= x*y; target++) {
                calls[i+1][target] += calls[i][j];
            }
        }
    }

    // Return count of last column where z <= 0
    int result = 0;
    for (int j = x*y; z-j <= 0; j--) {
        result += calls[x][j];
    }
    return result;
}

要了解,请查看此高科技Excel表格:

Call stack visualisation

此图表说明了sum(3, 3, 3)的来电。水平地你看到x和垂直你看到z都变得更小。 y是3而且没有改变。

左上角1表示对sum(3, 3, 3)的一次调用。然后,此调用会产生三个子调用(因为y = 3):sum(2, 2, 3)sum(1, 2, 3)sum(0, 2, 3)。这三个调用可以在下一列中找到(其中x = 2)。

然后,这三个调用中的每一个再次产生三个调用,显示在x = 1的行中。关于z,这九个调用有点重叠。然后,这九个呼叫中的每一个再次产生三个呼叫,导致在x = 0列中进行27次呼叫。

要获得结果,您只需计算x = 0列中的所有调用,其中z <= 0.在此示例中,这是每次调用,因此得到的结果为27.对于更大的z,结果将是小一点。

答案 1 :(得分:0)

public static double sum(int z, int x, int y) {
    int num = 0;    
    for (int i = 0; i <= y; i++) {
        if (z - x - i > 0) {
            num++;
        }
    }

    return (double) (Math.pow(y, x) - num);
}

说明:您的方法最多会在y^x个递归调用中启动。在递归的最后一级,x == 0,您必须在所有呼叫中确定z的最大值,并检查这些呼叫中有多少有z > 0,以便呼叫返回0,您不必考虑它。现在,在递归的最后一级,z的最大值由z - x给出。现在,您只需计算for循环中z - x保持正数的所有实例,这样就不会影响您的总和。计算出该数字后,从结果的初始近似值中减去它,即y^x