Leetcodeバイナリツリーの順序どおりのトラバーサル-Pythonは3つのソリューションを実装します

0トピックの説明

Leetcodeの元のタイトルへのリンク:バイナリツリーの順序どおりのトラバース
ここに写真の説明を挿入

# 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再帰的アルゴリズム

アイデアとアルゴリズム
まず、バイナリツリーの順序どおりのトラバースとは何かを理解する必要があります。左側のサブツリー-ルートノード-右側のサブツリーにアクセスする方法でこのツリーをトラバースし、左側のサブツリーまたは右側のサブツリーにアクセスするときは、次のようにします。ツリー全体がトラバースされるまで、同じ方法でトラバースします。したがって、トラバーサルプロセス全体は自然に再帰的であり、再帰関数を使用してこのプロセスを直接シミュレートできます。
定義inorder(root)は、現在ルートノードにトラバースされている回答を表します。定義によれば、inorder(root.left)を再帰的に呼び出してルートノードの左側のサブツリーをトラバースし、ルートノードの値を回答に追加してから、再帰的にinorderを呼び出すだけです。 (root.right)ルートノードの右側のサブツリーをトラバースするための再帰的終了の条件は、空のノードに遭遇することです。

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

アルゴリズムの複雑さ
時間の複雑さ:O(n)O(n)O n 、ここでnnnはバイナリツリーノードの数です。バイナリツリーのトラバーサルでは、各ノードに1回だけアクセスします。
スペースの複雑さ:O(n)O(n)O n スペースの複雑さは再帰的なスタックの深さに依存し、バイナリツリーがチェーンの場合、スタックの深さはO(n)O(n)に達する可能性がありますO n レベル。

2反復アルゴリズム(スタック)

再帰関数を反復的に実装することもできます。2つの方法は同等です。違いは、スタックは再帰中に暗黙的に維持されるため、反復時にこのスタックを明示的にシミュレートする必要があることです。

# 其核心思想如下:
# 使用颜色标记节点的状态,新节点为白色,已访问的节点为灰色。
# 如果遇到的节点为白色,则将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈。
# 如果遇到的节点为灰色,则将节点的值输出。
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

アルゴリズムの複雑さ
時間の複雑さ:O(n)O(n)O n 、ここでnnnはバイナリツリーノードの数です。バイナリツリーのトラバーサルでは、各ノードに1回だけアクセスします。
スペースの複雑さ:O(n)O(n)O n スペースの複雑さは再帰的なスタックの深さに依存し、バイナリツリーがチェーンの場合、スタックの深さはO(n)O(n)に達する可能性がありますO n レベル。

3モリスインオーダートラバーサル

アイデアとアルゴリズム
モリストラバーサルアルゴリズムは、バイナリツリーをトラバースするもう1つの方法であり、O(1)への非再帰的な順序トラバーサルのスペースの複雑さを軽減できます。
モリストラバーサルは一定のスペーストラバーサルメソッドであり、その本質はスレッド化されたバイナリツリー(スレッド化されたバイナリツリー)であり、本質的には、バイナリツリー内のNULLへのn +1ポインタを実際に使用します。
トラバーサルプロセス中、モリストラバーサルは、リーフノードの空の右ポインターを使用して、順序どおりのトラバーサルの後続ノードを指すため、スタックへの依存を回避します。ここに写真の説明を挿入
ここに写真の説明を挿入

# (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

アルゴリズムの複雑さ
時間の複雑さ:O(n)O(n)O n 、ここでnnnは、バイナリ検索ツリー内のノードの数です。モリストラバーサルでは、各ノードが2回訪問されるため、合計時間の複雑さはO(2 n)O(2n)です。O 2 n =O(n)O(n)O n
スペースの複雑さ:O(1)O(1)O 1

参照

色表記-ツリートラバーサルの一般的で簡潔な方法
モリストラバーサル

おすすめ

転載: blog.csdn.net/OuDiShenmiss/article/details/109197755