Java 如何转换为尾部递归

Java 如何转换为尾部递归,java,recursion,tail-recursion,Java,Recursion,Tail Recursion,我理解什么是尾部递归,但我在将此方法转换为尾部递归时遇到困难。我试图计算矩阵中有多少相邻元素。因此,我的问题是如何将其转化为尾部递归 public static int ExploreAndLabelColony(char[][] grid, int i, int j, char c,int count) { grid[i][j] = c; count = 1; if ((i>0 && i<grid.length &a

我理解什么是尾部递归,但我在将此方法转换为尾部递归时遇到困难。我试图计算矩阵中有多少相邻元素。因此,我的问题是如何将其转化为尾部递归

public static int ExploreAndLabelColony(char[][] grid, int i, int j, char c,int count) { 
        grid[i][j] = c;
        count = 1;
        if ((i>0 && i<grid.length && j<grid[0].length) && (grid[i-1][j] == '1')) { //vertical bottom
            count +=ExploreAndLabelColony(grid, i-1,j,c,count); 
            }
        if (i+1<grid.length && j<grid[0].length && grid[i+1][j] == '1') { //vertical top
            count+=ExploreAndLabelColony(grid, i+1,j  ,c,count); 
            }
        if (j>0 && i<grid.length && j<grid[0].length && grid[i][j-1] == '1') { //horizontal left
            count +=ExploreAndLabelColony(grid, i,j-1  ,c,count); 
            }
        if (i<grid.length && j+1<grid[0].length && grid[i][j+1] == '1') { //horizontal right
            count+=ExploreAndLabelColony(grid, i,j+1  ,c,count); 
            }
        if (i+1<grid.length && j+1<grid[0].length && grid[i+1][j+1] == '1') { //diagonal bottom right
            count+=ExploreAndLabelColony(grid, i+1,j+1  ,c,count);
            } 
        if (j>0 && i+1<grid.length && j<grid[0].length && grid[i+1][j-1] == '1') { //diagonal bottom right
            count+=ExploreAndLabelColony(grid, i+1,j-1  ,c,count);
            } 
        if (i>0 && i<grid.length && j+1<grid[0].length && grid[i-1][j+1] == '1') { //diagonal top right
            count+=ExploreAndLabelColony(grid, i-1,j+1  ,c,count);
            } 
        if (i>0 && j>0 && i<grid.length && j<grid[0].length && grid[i-1][j-1] == '1') { //diagonal top left
            count+=ExploreAndLabelColony(grid, i-1,j-1  ,c,count);
            }
            
        return count;
    }
public static int exploreandLabelClony(char[][]网格,int i,int j,char c,int count){
网格[i][j]=c;
计数=1;

如果((i>0&&i这可能符合尾部递归:

static class Queue {
    int i;
    int j;
    Queue next;
    Queue(int i, int j, Queue next) {
        this.i = i;
        this.j = j;
        this.next = next;
    }
}

int exploreAndLabel(char[][] grid, int i, int j, char c) {
    return exploreAndLabel(new Queue(i, j, null), grid, c, 0);
}

int exploreAndLabel(Queue queue, char[][] grid, char c, int count) {
    if (queue == null) {
        return count; // no more work
    }
    int i = queue.i;
    int j = queue.j;
    queue = queue.next;
    if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) {
        // outside grid
    } else if (grid[i][j] != '1') {
        // outside colony
    } else {
        grid[i][j] = c;  // label
        count++;
        queue = new Queue(i - 1, j - 1, queue);
        queue = new Queue(i - 1, j, queue);
        queue = new Queue(i - 1, j + 1, queue);
        queue = new Queue(i, j - 1, queue);
        queue = new Queue(i, j + 1, queue);
        queue = new Queue(i + 1, j - 1, queue);
        queue = new Queue(i + 1, j, queue);
        queue = new Queue(i + 1, j + 1, queue);
    }
    return exploreAndLabel(queue, grid, c, count);
}

为此,我需要一个有效的测试用例——这个方法可以设置一个简单的网格,调用
exploreandlabeloclony
,并验证预期的返回值。(我的尝试产生了java.lang.StackOverflowerr,没有双关语)看看你的算法,你可以在返回之前进行多达八次递归调用“尾部递归”您的意思是以
returnexploreandlabelclony(…)结束方法
您可能需要更改算法,使其只需要一个递归调用。我如何更改算法,使其只需要一个递归调用?@ErikWhy您想转换为尾部递归吗?Java不做尾部递归优化,因此这样做没有任何好处。因为我的老师让我做@andreas“exploreAndLabel”方法的时间复杂度?@ErikI认为应该是O(n)(其中n是网格中的单元数)
@Test
public void testTailRecursion() {
    char[][] grid = Stream.of(
            "00000101",
            "00001101",
            "00111010")
            .map(String::toCharArray)
            .toArray(char[][]::new);

    int count = exploreAndLabel(grid, 2, 3, '2');
    Assert.assertEquals(9, count);
}