12
votes

Chemin le plus long entre 2 nœuds

Calculez le chemin le plus long entre deux nœuds.
Le chemin est dans une arche.
La signature de la méthode est la suivante: xxx

dans l'exemple d'arbre binaire ci-dessous, il est 4 (aller jusqu'au 2-3-13-5-2).

C'est ce que j'ai maintenant et pour l'arbre donné Il suffit de retourner 0. xxx

Je crois que je manque un concept clé quelque part ... mon cerveau devient fou quand j'essaie de suivre le flux d'exécution ...
Suis-je raison en disant que, en trouvant le chemin le plus long parmi la racine, ses nœuds de gauche et de droite puis recueille sur ses nœuds de gauche et de droite les transmettent le chemin le plus long de l'invocation de la méthode précédente et enfin (quand?) Retournez le chemin le plus long, je Je ne suis pas certain de savoir comment vous allez le retourner ...


1 commentaires

Comment gérez-vous le cas où l'arbre binaire est essentiellement une liste liée? Par exemple, le 2-3-13 (13 est la racine 3 à gauche de 13 et 2 est laissé de 3). Si le résultat soit 2?


9 Réponses :


14
votes

Peut-être que c'est aussi simple: xxx

c'est plus compliqué que celui qui pourrait penser à première vue. Considérons l'arborescence suivante: xxx

Dans ce cas, le nœud racine n'est même pas dans le chemin le plus long ( A-7-4-2-5-8- b ).

Donc, ce que vous devez faire est ce que vous devez faire est ce que vous devez faire est ce qui suit: Pour chaque nœud n , vous devez calculer ce qui suit:

  • Compute le chemin le plus long dans la sous-arbre gauche commençant par la racine de la sous-arbre gauche (appelée l )
  • Compute le chemin le plus long dans le sous-arbre droit commençant par la racine du sous-arbre de droite (appelé r )
  • calculer le chemin le plus long dans le sous-arbre gauche (pas nécessairement en commençant par la racine du sous-arbre gauche) (appelé l )
  • calculer le chemin le plus long dans le sous-arbre droit (pas nécessairement en commençant par la racine du sous-arbre de droite) (appelé r )

    puis décidez, quelle combinaison maximise la longueur du chemin:

    • l + r + 2 , c'est-à-dire d'un sous-path dans le sous-arbre de gauche au nœud actuel et du nœud actuel à travers un sous-path dans le sous-arbre droit
    • l , c'est-à-dire juste prendre la sous-arbre de gauche et exclure le nœud actuel (et donc le sous-arbre à droite) du chemin
    • r , c'est-à-dire juste prendre le sous-arbre de droite et exclure le nœud actuel (et donc laissé sous-arbre) du chemin

      Donc, je ferais un petit piratage et que chaque nœud ne renvoie pas juste un seul int , mais un triple d'entiers contenant (l + r + 2, l, r) . L'appelant doit alors décider de ce qu'il faut faire avec ce résultat selon les règles ci-dessus.


6 commentaires

Merci, mais j'ai essayé et ça retourne juste zéro. Quant à moi oublier d'ajouter le retour, je l'ai ajouté et il a enregistré 4, mais cela ne représente que la voûte s'étendant du nœud racine ... Autres arches plus longtemps qu'il n'était simplement ignoré.


En fait, le chemin le plus long est de 6 (par exemple: A-7-4-2-5-8-B). C'est un bon exemple, cependant.


@Daniel Hmmm comme je l'ai compris que le chemin est de la forme d'une arche (à l'envers V).


@timenomad: Vous devrez peut-être demander des éclaircissements à votre instructeur. 9-7-4-2-5-8-B est toujours "une arche" pour moi. Voir aussi: en.wikipedia.org/wiki/path_(Graph_Theory)


Pourquoi avons-nous besoin l et r ? Je ne suis pas capable de penser à un cas d'angle où l + r + 2 ne fera pas le tour.


Aussi pourquoi est-ce l + r + 2 ? Ne devrait-il pas être l + r + 1 ? Pour le nœud 2 L est 3 (4-7-a / 9) et R est 3 (5-8-B) de sorte que la longueur sera 3 + 3 + 1 [pour noeud racine] ?



12
votes

Un algorithme correct est:

  1. Exécutez DFS de tout nœud pour trouver le nœud de feuille le plus éloigné. Étiquette que le nœud t.
  2. Exécutez un autre DFS pour trouver le nœud le plus éloigné de T.
  3. Le chemin que vous avez trouvé à l'étape 2 est le chemin le plus long de l'arbre.

    Cet algorithme fonctionnera certainement et vous n'êtes pas limité aux arbres binaires non plus. Je ne suis pas sûr de votre algorithme:

    Je suis juste en disant que, en trouvant le chemin le plus long parmi la racine, ses nœuds de gauche et de droite, puis recueillent sur ses nœuds de gauche et de droite qui leur transmet le plus long chemin de l'invocation de la méthode précédente et enfin (quand ???) Retourner Le chemin le plus long, je ne suis pas certain de la façon dont vous allez le retourner ...

    Parce que je ne comprends pas ce que vous décrivez exactement. Pouvez-vous le travailler à la main sur un exemple ou essayer de mieux l'expliquer? De cette façon, vous pourriez avoir une meilleure aide à comprendre si c'est correct ou non.

    Vous semblez essayer d'une mise en œuvre récursive de la même chose simplement simplifiée pour les arbres binaires. Votre code semble plutôt compliqué pour ce problème cependant. Vérifiez la discussion ici pour une implémentation plus simple.



1
votes

Je pense que vous êtes surcharge des choses.

Pensez au chemin le plus long qui traverse le nœud N et ne mène pas au parent de n. Quelle est la relation entre la longueur de ce chemin et les hauteurs des deux sous-groupes reliés à N?

Après avoir compris cela, vérifiez l'arborescence de raisonnement récursivement comme celui-ci:

Le chemin le plus long pour un sous-arbre avec la racine N est le chemin le plus long des trois suivants:

  1. Le chemin le plus long dans le sous-arbre, dont la racine est N.LEFT_CHILD
  2. Le chemin le plus long dans le sous-arbre, dont la racine est N.Right_Child
  3. Le chemin le plus long, qui passe par le nœud N et ne mène pas au parent de n

0 commentaires


1
votes

Eh bien, Umm si j'ai bien compris votre question correctement, voici ma solution [mais en C ++ (je suis désolé)]: XXX


0 commentaires

2
votes

Voici ma solution récursive en C ++:

int longest_dis(Node* root) {
    int height1, height2;

    if( root==NULL)
        return 0;

    if( root->left == NULL ) && ( root->right == NULL )
        return 0;

    height1 = height(root->left); // height(Node* node) returns the height of a tree rooted at node
    height2 = height(root->right);

    if( root->left != NULL ) && ( root->right == NULL )
        return max(height1+1, longest_dis(root->left) );

    if( root->left == NULL ) && ( root->right != NULL )
        return max(height2+1, longest_dis(root->right) );

    return max(height1+height2+2, longest_dis(root->left), longestdis(root->right) );
}


0 commentaires

2
votes
public int longestPath() {
    int[] result = longestPath(root);
    return result[0] > result[1] ? result[0] : result[1];
}

// int[] {self-contained, root-to-leaf}
private int[] longestPath(BinaryTreeNode n) {
    if (n == null) {
        return new int[] { 0, 0 };
    }
    int[] left = longestPath(n.left);
    int[] right = longestPath(n.right);

    return new int[] { Util.max(left[0], right[0], left[1] + right[1] + 1),
            Util.max(left[1], right[1]) + 1 };
}

0 commentaires

2
votes

Mise en œuvre simple:

int maxDepth(Node root) {
    if(root == null) {
        return 0;
    } else {
        int ldepth = maxDepth(root.left);
        int rdepth = maxDepth(root.right);
        return ldepth>rdepth ? ldepth+1 : rdepth+1;
    }
}

int longestPath(Node root)
{
   if (root == null)
     return 0;

  int ldepth = maxDepth(root.left);
  int rdepth = maxDepth(root.right);

  int lLongPath = longestPath(root.left);
  int rLongPath = longestPath(root.right);

  return max(ldepth + rdepth + 1, max(lLongPath, rLongPath));
}


1 commentaires

Ce serait O (n ^ 2). Il devrait y avoir une meilleure solution de O (n)



2
votes

Prendre en compte @Phimuemue Exemple et @IVLAD Solution, j'ai décidé de vérifier moi-même, alors voici ma mise en œuvre de la solution @IVLAD en Python:

def longestPath(graph,start, path=[]):
    nodes = {}
    path=path+[start]
    for node in graph[start]:
        if node not in path:
            deepestNode,maxdepth,maxpath = longestPath(graph,node,path)
            nodes[node] = (deepestNode,maxdepth,maxpath)
    maxdepth = -1
    deepestNode = start
    maxpath = []
    for k,v in nodes.iteritems():
        if v[1] > maxdepth:
            deepestNode = v[0]
            maxdepth = v[1]
            maxpath = v[2]
    return deepestNode,maxdepth +1,maxpath+[start]

if __name__ == '__main__':
    graph = { '1' : ['2','3'],
              '2' : ['1','4','5'],
              '3' : ['1'],
              '4' : ['2','6','7'],
              '5' : ['2','8'],
              '6' : ['4'],
              '7' : ['4','9','a'],
              '8' : ['5','b'],
              '9' : ['7'],
              'a' : ['7'],
              'b' : ['8']
    }
    """
          1
         / \
        2   3
       / \
      4   5
     / \   \
    6   7   8
       / \   \
      9   a   b
    """
    deepestNode,maxdepth,maxpath = longestPath(graph,'1')
    print longestPath(graph, deepestNode)

>>> ('9', 6, ['9', '7', '4', '2', '5', '8', 'b'])


0 commentaires