Se trata de un [problema unión-]: https://leetcode.com/problems/similar-string-groups/
Si cambio de la línea parents[find(j)] = i;
en parents[find(i)] = j;
, el código resultará en un desbordamiento de pila. Al parecer, el camino es demasiado profundo para el método de búsqueda recursiva (). Pero no puedo decir qué diferencia hace este cambio marca. ¿Alguien puede ayudar?
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;
}
}
Usando parents[find(i)] = j
permite un valor para ser más pequeño que su índice repitiendo el valor que los índices pueden ser. Esto puede resultar en una situación en la que 2 elementos tienen índices / valores Inversed uno del otro. Por ejemplo:
Teniendo en cuenta A.length == 5
, la matriz de partida se vería así:
padres [0] = 0; padres [1] = 1; padres [2] = 2; padres [3] = 3; padres [4] = 4;
Los valores que utilizamos serán para similar
devolver cierto. Comenzando con i = 2, j = 1
, esto haría que las llamadas:
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;
A continuación, 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;
entonces 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;
Se puede ver ahora que tenemos nuestro bucle infinito creó ( parents[1] = 2; parents[2] = 1
). Si find
se llama con 1 o 2, este se queda bloqueado entre estos dos valores. Necesitamos dos pasos más para llegar allí. 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;
Por último, i = 4, j = 2
:
find(4); find(1); find(2); find(1); find(2); find(1); find(2); ...
El uso de parents[find(j)] = i
medios que el valor asignado no puede convertirse en menor porque i
siempre incrementos mientras j
se repite para cada iteración de i
. j
puede ser cualquier valor de 0 to i -1
.