Traversée dans l'ordre de l'arbre binaire Leetcode - Python implémente trois solutions

0 description du sujet

Lien vers le titre original Leetcode: Parcours dans l'ordre de l'arbre binaire
Insérez la description de l'image ici

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

1 Algorithme récursif

Idées et algorithmes
Tout d'abord, nous devons comprendre ce qu'est la traversée dans l'ordre d'un arbre binaire: traversez cet arbre de la manière de visiter le sous-arbre gauche sous-arbre-racine nœud-droit, et lors de la visite du sous-arbre gauche ou du sous-arbre droit, nous suivons Parcourez de la même manière jusqu'à ce que l'arbre complet soit parcouru. Par conséquent, l'ensemble du processus de parcours est naturellement récursif, et nous pouvons directement simuler ce processus avec une fonction récursive.
La définition inorder (root) représente la réponse actuellement parcourue vers le nœud racine, puis selon la définition, il suffit d'appeler récursivement inorder (root.left) pour traverser le sous-arbre gauche du nœud racine, puis ajouter la valeur du nœud racine à la réponse, puis appeler de manière récursive inorder (root.right) Pour traverser le sous-arbre droit du nœud racine, la condition pour une terminaison récursive est de rencontrer un nœud vide.

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)

Complexité de l'algorithme Complexité du
temps: O (n) O (n)O ( n ) , oùnnn est le nombre de nœuds d'arbre binaire. Dans le parcours de l'arbre binaire, chaque nœud sera visité une et une seule fois.
Complexité spatiale:O (n) O (n)O ( n ) . La complexité de l'espace dépend de la profondeur de la pile récursive, et la profondeur de la pile peut atteindreO (n) O (n)lorsque l'arbre binaire est une chaîneNiveau O ( n ) .

2 Algorithme itératif (pile)

Nous pouvons également implémenter des fonctions récursives de manière itérative. Les deux méthodes sont équivalentes. La différence est qu'une pile est implicitement maintenue pendant la récursivité, et nous devons simuler explicitement cette pile lors de l'itération.

# 其核心思想如下:
# 使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。
# 如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。
# 如果遇到的节点为灰色,则将节点的值输出。
class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        White, Gray = 0, 1
        res = []
        stack = [(White,root)]
        while stack:
            color, node = stack.pop()
            if not node: continue
            if color == White:
                stack.append((White,node.right))
                stack.append((Gray,node))
                stack.append((White,node.left))
            else:
                res.append(node.val)
        return res

Complexité de l'algorithme Complexité du
temps: O (n) O (n)O ( n ) , oùnnn est le nombre de nœuds d'arbre binaire. Dans le parcours de l'arbre binaire, chaque nœud sera visité une et une seule fois.
Complexité spatiale:O (n) O (n)O ( n ) . La complexité de l'espace dépend de la profondeur de la pile récursive, et la profondeur de la pile peut atteindreO (n) O (n)lorsque l'arbre binaire est une chaîneNiveau O ( n ) .

3 Traversée dans l'ordre de Morris

Idées et algorithmes
L'algorithme de parcours de Morris est une autre méthode de traversée d'arbres binaires, qui peut réduire la complexité spatiale de la traversée non récursive dans l'ordre vers O (1).
Morris traversal est une méthode de traversée d'espace constant, son essence est un arbre binaire fileté (Threaded Binary Tree), en fait, il utilise en fait n + 1 pointeurs vers NULL dans l'arbre binaire.
Pendant le processus de traversée, Morris traversal utilise le pointeur droit vide du nœud feuille pour pointer vers le nœud successeur de la traversée dans l'ordre, évitant ainsi la dépendance à la pile.Insérez la description de l'image ici
Insérez la description de l'image ici

# (1)对于一个节点cur,找到它左子树的最右节点,看这个节点的right指针是null还是指向cur。
# (2)如果是null,说明左子树还没处理过,更新该指针为cur,然后进入左子树继续上述流程。
# (3)如果该指针已经是cur了,说明左子树已经处理完毕,现在是处理完毕后顺这最右节点的right指针回到该cur节点的,需先将该right指针恢复为null,处理该cur节点后进入右子树重复流程⑴。
class Solution:
    def inorderTraversal(self, root: TreeNode) -> list:
        node, res = root, []
        while node:
            if not node.left:
                res.append(node.val)
                node = node.right
            else:
                pre = node.left
                while pre.right and pre.right != node:
                    pre = pre.right
                if not pre.right:
                    pre.right = node
                    node = node.left
                else:
                    pre.right = None
                    res.append(node.val)
                    node = node.right
        return res

Complexité de l'algorithme Complexité du
temps: O (n) O (n)O ( n ) , oùnnn est le nombre de nœuds dans l'arbre de recherche binaire. Dans le parcours de Morris, chaque nœud sera visité deux fois, donc la complexité temporelle totale estO (2 n) O (2n)O ( 2 n ) =O (n) O (n)O ( n ) .
Complexité spatiale:O (1) O (1)O ( 1 )

référence

Notation des couleurs - une méthode générale et concise de traversée d'arbre
Morris traversal

Je suppose que tu aimes

Origine blog.csdn.net/OuDiShenmiss/article/details/109197755
conseillé
Classement