为什么更改代码中的一行会导致堆栈溢出?

时间:2019-06-18 02:32:50

标签: java recursion stack-overflow union-find

这是一个[工会发现的问题]:https://leetcode.com/problems/similar-string-groups/

如果将行parents[find(j)] = i;更改为parents[find(i)] = j;,则代码将导致堆栈溢出。显然,该路径对于递归find()方法而言太深了。但是我不能说这个改变有什么不同。有人可以帮忙吗?

class Solution {
    int[] parents;
    public int numSimilarGroups(String[] A) {
        parents = new int[A.length];
        for(int i = 0;i < parents.length;i++) {
            parents[i] = i;
        }
        for(int i = 0;i < A.length;i++) {
            for(int j = 0;j < i;j++) {
                if(similar(A[i],A[j])) {
                    parents[find(j)] = i;
                }
            }
        }
        int ans = 0;
        for(int i = 0;i < parents.length;i++) {
            if(parents[i] == i)
                ans++;
        }
        return ans;
    }

    private int find(int curr) {
        int p = parents[curr];
        if(p != curr) {
            int pp = find(p);
            parents[curr] = pp;
        }
        return parents[curr];
    }

    private boolean similar(String a, String b) {
        int diff = 0;
        int i = 0;
        boolean consecutive = false;
        while(diff <= 2 && i < a.length()) {
            if(a.charAt(i) != b.charAt(i))
                diff++;
            if(i > 0 && a.charAt(i) == a.charAt(i-1))
                consecutive = true;
            i++;
        }
        return diff == 2 || diff == 0 && consecutive;
    }
}

1 个答案:

答案 0 :(得分:2)

使用parents[find(i)] = j可以通过重复索引可以变成的值来使其值小于其索引。这可能导致2个元素的索引/值彼此相反的情况。例如:

给出A.length == 5,您的起始数组将如下所示:

  

父母[0] = 0;父母[1] = 1;父母[2] = 2;父母[3] = 3;父母[4] = 4;

我们将使用similar返回true的值。从i = 2, j = 1开始,将进行呼叫:

find(2);    //Array doesn't change in recursive function

//Resulting array after applying j to parents[2]:
//          parents[0] = 0; parents[1] = 1; parents[2] = 1; parents[3] = 3; parents[4] = 4;

接下来,i = 3, j = 1

find(3);    //Array doesn't change in recursive function

//Resulting array after applying j to parents[3]:
//          parents[0] = 0; parents[1] = 1; parents[2] = 1; parents[3] = 1; parents[4] = 4;

然后i = 3, j = 2

find(3); find(1);    //Array doesn't change in recursive function

//Resulting array after applying j to parents[1]:
//          parents[0] = 0; parents[1] = 2; parents[2] = 1; parents[3] = 1; parents[4] = 4;

您现在可以看到我们已经设置了无限循环(parents[1] = 2; parents[2] = 1)。如果用1或2调用find,这将卡在这两个值之间。我们还需要两个步骤才能达到目标。 i = 4, j = 1

find(4);    //Array doesn't change in recursive function

//Resulting array after applying j to parents[1]:
//          parents[0] = 0; parents[1] = 2; parents[2] = 1; parents[3] = 1; parents[4] = 1;

最后,i = 4, j = 2

find(4); find(1); find(2); find(1); find(2); find(1); find(2); ...

使用parents[find(j)] = i意味着分配的值不会变小,因为i总是递增,而j对于i的每次迭代都会重复。 j可以是0 to i -1的任何值。