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


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

    题目截图

    方法一:递归

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

    1. class Solution:
    2. def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    3. self.result = []
    4. if root == None:
    5. return self.result
    6. self.result = self.inorderTraversal(root.left) + [root.val] \
    7. + self.inorderTraversal(root.right)
    8. return self.result

    复杂度分析

    时间复杂度:O(n)

    空间复杂度:O(n)

     

    完整测试代码:

    1. from typing import Optional,List
    2. class TreeNode:
    3. def __init__(self, val=0, left=None, right=None):
    4. self.val = val
    5. self.left = left
    6. self.right = right
    7. class Solution:
    8. def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    9. self.result = []
    10. if root == None:
    11. return self.result
    12. self.result = self.inorderTraversal(root.left) + [root.val] \
    13. + self.inorderTraversal(root.right)
    14. return self.result
    15. class main:
    16. a = Solution()
    17. root3 = TreeNode(3, left=None, right=None)
    18. root2 = TreeNode(2, left=root3, right=None)
    19. root = TreeNode(1, left = None, right= root2)
    20. b = a.inorderTraversal(root)
    21. print(b)
    22. if __name__ == '__main__':
    23. main()

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

    方法二:迭代法

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

    两层循环

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

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

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

    1. class Solution:
    2. def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    3. if root == None:
    4. return []
    5. result, stack = list(), list()
    6. current = root
    7. while current or len(stack):
    8. while current:
    9. stack.append(current)
    10. current = current.left
    11. node = stack.pop()
    12. result.append(node.val)
    13. current = node.right
    14. return result

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

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

    1. class Solution:
    2. def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    3. if root == None:
    4. return []
    5. result, stack = [], []
    6. while root or stack:
    7. if root:
    8. stack.append(root)
    9. root = root.left
    10. else:
    11. cur = stack.pop()
    12. result.append(cur.val)
    13. root = cur.right
    14. 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

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

    1. class Solution:
    2. def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
    3. result = []
    4. current, prev = root, None
    5. while current:
    6. if not current.left:
    7. result.append(current.val)
    8. current = current.right
    9. else:
    10. prev = current.left
    11. while prev.right and prev.right != current:
    12. prev = prev.right
    13. if not prev.right:
    14. prev.right = current
    15. current = current.left
    16. else:
    17. prev.right = None
    18. result.append(current.val)
    19. current = current.right
    20. return result

    复杂度分析

     时间复杂度O(n)

    空间复杂度O(1)

    参看力扣官方解析

  • 相关阅读:
    彻底了解线程池的原理——40行从零开始自己写线程池
    JavaScript 63 JavaScript 对象 63.1 JavaScript 对象定义
    Eureka Server 实现在线扩容
    一文讲清生产质量场景的数据分析思路及案例实战
    10 大最佳网络分析工具介绍
    简单软光栅实现
    Redis集群部署
    测试工程师如何帮助开发域的质量变好
    洛谷P2619 [国家集训队]Tree I
    几个常见的js手写题,你能写出来几道
  • 原文地址:https://blog.csdn.net/weixin_42112343/article/details/126179135