LeetCode #94.二叉树的中序遍历

力扣 | 94. 二叉树的中序遍历

题目截图

LeetCode #94.二叉树的中序遍历_第1张图片

方法一:递归

中序遍历是左根右的顺序,当访问左结点时,左节点可以看成一个左子树的根节点,依然按照左根右的顺序遍历。同理,右结点也是。直到遍历完整个二叉树。整个过程都在递归。

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

复杂度分析

时间复杂度:O(n)

空间复杂度:O(n)

 

完整测试代码:

from typing import Optional,List

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

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


class main:
    a = Solution()
    root3 = TreeNode(3, left=None, right=None)
    root2 = TreeNode(2, left=root3, right=None)
    root = TreeNode(1, left = None, right= root2)


    b = a.inorderTraversal(root)
    print(b)


if __name__ == '__main__':
    main()

LeetCode只需要写题目算法部分不需要写完整的实现部分。本题给出的条件是输入为root = [1,null,2,3],而本解答给出的完整实现的方法是利用TreeNode一个一个的添加节点。如果要直接使用 root = [1,null,2,3]作为输入条件需要再写一个有序列表转换为二叉树的算法。

方法二:迭代法

建立一个栈,然后遍历二叉树。

两层循环

内层循环:将二叉树的根节点一直和左节点存入栈中。然后指针左移, 将左节点的左子节点存入栈中,只要指针指向的结点存在就一直重复此动作,直到指针指向为空。

外层循环:然后出栈一个节点,将该节点的值填入输出结果中,并将指针指向该出栈结点的右节点。

以此完成左根右的中序遍历。

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if root == None:
            return []

        result, stack = list(), list()
        current = root
        while current or len(stack):
            while current:
                stack.append(current)
                current = current.left
            node = stack.pop()
            result.append(node.val)
            current = node.right
        return result

这种方式的迭代法又两层循环,复杂度较高。

还是按照这个思路,内外循环改为判断。

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if root == None:
            return []

        result, stack = [], []
        while root or stack:
           if root:
               stack.append(root)
               root = root.left
           else:
               cur = stack.pop()
               result.append(cur.val)
               root = cur.right

        return result

复杂度分析

 时间复杂度:O(n)

空间复杂度:O(n)

方法三:Morris中序遍历

一、如果x无左孩子,先将x的值加入答案组,再访问x的右孩子,即x=x.right

二、如果x有左孩子,则找到x左子树上最右的结点(即左子树中序遍历的最后一个结点),记为predecessor。根据predecessor的右孩子是否为空进行如下操作。

(1)如果predecessor的右孩子为空,则将其右孩子指向x,然后访问x的左孩子,即x=x.left

 (2)如果predecessor的右孩子不为空,则此时右孩子已经指向x,说明已经遍历完x的左子树,将predecessor的右孩子置空,将x的值加入答案数组,然后访问x的右孩子,即x=x.right

三、重复上述操作,直至访问完整棵树。

class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        result = []
        current, prev = root, None
        while current:
            if not current.left:
                result.append(current.val)
                current = current.right
            else:
                prev = current.left
                while prev.right and prev.right != current:
                    prev = prev.right
                if not prev.right:
                    prev.right = current
                    current = current.left
                else:
                    prev.right = None
                    result.append(current.val)
                    current = current.right
        return result

复杂度分析

 时间复杂度O(n)

空间复杂度O(1)

参看力扣官方解析

你可能感兴趣的:(leetcode,算法,python,数据结构)