码迷,mamicode.com
首页 > 其他好文 > 详细

LeetCode: 二叉树的遍历

时间:2021-04-05 11:47:20      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:epo   null   repos   结果   构造二叉树   self   验证   ack   深度   

二叉树的遍历

前序遍历

LeetCode.144. 二叉树的前序遍历

二叉树的前序/中序/后序遍历的非递归描述一般适合用深度优先搜索 (DFS, depth-first search), 并使用栈的数据结构.

版本1 递归

from typing import List

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

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        res = []
        def dfs(root):
            if not root:
                return None
            res.append(root.val)
            dfs(root.left)
            dfs(root.right)
        dfs(root)
        return res

版本2 递归

class Solution:
    def __init__(self):
        self.res = []
    
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        self.res.append(root.val)
        self.preorderTraversal(root.left)
        self.preorderTraversal(root.right)
        return self.res

版本3 非递归

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        res = []
        stack_node = []
        while root or stack_node:
            if root:
                res.append(root.val)
                stack_node.append(root.right)
                root = root.left
            else:
                root = stack_node.pop()
        return res

中序遍历

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

from typing import List

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

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        res = []
        stack_node = []
        while root or stack_node:
            if root:
                stack_node.append(root)
                root = root.left
            else:
                root = stack_node.pop()
                res.append(root.val)
                root = root.right
        return res

后序遍历

LeetCode.145. 二叉树的后序遍历

from typing import List

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

class Solution:
    def postorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        res = []
        stack_node = []
        seen = None
        while root or stack_node:
            while root:
                stack_node.append(root)
                root = root.left
            root = stack_node.pop()
            if not root.right or root.right is seen:
                res.append(root.val)
                seen = root
                root = None
            else:
                stack_node.append(root)
                root = root.right
        return res

层序遍历

二叉树的层序遍历

LeetCode.102. 二叉树的层序遍历

示例:
二叉树: [3,9,20,null,null,15,7],
    3
   /   9  20
    /     15   7
返回其层序遍历结果:
[
  [3],
  [9,20],
  [15,7]
]

二叉树的层序遍历一般适合用广度优先搜索 (BFS, breadth-first search), 并使用队列的数据结构.

from typing import List
from collections import deque

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

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res = []
        queue = deque()
        queue.append(root)
        while queue:
            temp = []
            for i in range(len(queue)):
                cur = queue.popleft()
                temp.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            res.append(temp)
        return res

二叉树的锯齿形层序遍历

LeetCode.103. 二叉树的锯齿形层序遍历

示例:
二叉树: [3,9,20,null,null,15,7],
    3
   /   9  20
    /     15   7
返回锯齿形层序遍历如下:
[
  [3],
  [20,9],
  [15,7]
]

版本1

from typing import List
from collections import deque

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

class Solution:
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res = []
        queue = deque()
        queue.append(root)
        reverse = True
        while queue:
            temp = []
            reverse = not reverse
            for i in range(len(queue)):
                cur = queue.popleft()
                temp.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            if reverse:
                res.append(temp[::-1])
            else:
                res.append(temp)
        return res

版本2 temp 修改为双向队列结构

class Solution:
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res = []
        queue = deque()
        queue.append(root)
        reverse = True
        while queue:
            temp = deque()
            reverse = not reverse
            for i in range(len(queue)):
                cur = queue.popleft()
                if not reverse:
                    temp.append(cur.val)
                else:
                    temp.appendleft(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            res.append(list(temp))
        return res

二叉树的层序遍历 II

LeetCode.107. 二叉树的层序遍历 II

示例:
二叉树: [3,9,20,null,null,15,7],
    3
   /   9  20
    /     15   7
返回其自底向上的层序遍历为:
[
  [15,7],
  [9,20],
  [3]
]
from typing import List
from collections import deque

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

class Solution:
    def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res = deque()
        queue = deque()
        queue.append(root)
        while queue:
            temp = []
            for _ in range(len(queue)):
                cur = queue.popleft()
                temp.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            res.appendleft(temp)
        return list(res)

构造二叉树

从前序与中序遍历序列构造二叉树

LeetCode.105. 从前序与中序遍历序列构造二叉树

注: 遍历中的值是不同的正整数
给出: 
前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树: 
    3
   /   9  20
    /     15   7
from typing import List

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

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        if len(preorder) == 0:
            return None
        root = TreeNode(preorder[0])
        root_id = inorder.index(preorder[0])
        root.left = self.buildTree(preorder[1:root_id+1], inorder[:root_id])
        root.right = self.buildTree(preorder[root_id+1:], inorder[root_id+1:])
        return root

从中序与后序遍历序列构造二叉树

LeetCode.106. 从中序与后序遍历序列构造二叉树

给出: 
中序遍历 inorder = [9,3,15,20,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树: 
    3
   /   9  20
    /     15   7
from typing import List

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

class Solution:
    def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
        if len(inorder) == 0:
            return None
        root = TreeNode(postorder[-1])
        root_id = inorder.index(postorder[-1])
        root.left = self.buildTree(inorder[:root_id], postorder[:root_id])
        root.right = self.buildTree(inorder[root_id+1:], postorder[root_id:-1])
        return root

从前序与后序遍历序列构造二叉树

LeetCode.889. 根据前序和后序遍历构造二叉树

给出: 
前序遍历 preorder = [3,9,20,15,7]
后序遍历 postorder = [9,15,7,20,3]
返回如下的二叉树: 
    3
   /   9  20
    /     15   7
from typing import List

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

class Solution:
    def constructFromPrePost(self, pre: List[int], post: List[int]) -> TreeNode:
        if len(pre) == 0:
            return None
        root = TreeNode(pre[0])
        if len(pre) == 1:
            return root
        right_id = pre.index(post[-2])
        root.left = self.constructFromPrePost(pre[1:right_id], post[:right_id-1])
        root.right = self.constructFromPrePost(pre[right_id:], post[right_id-1:-1])
        return root

二叉树展开为链表

LeetCode.114. 二叉树展开为链表

给你二叉树的根结点 root, 请你将它展开为一个单链表: 
展开后的单链表应该同样使用 TreeNode, 其中 right 子指针指向链表中下一个结点, 而左子指针始终为 null.
展开后的单链表应该与二叉树先序遍历顺序相同.
输入: root = [1,2,5,3,4,null,6]
输出: [1,null,2,null,3,null,4,null,5,null,6]

版本1 递归, 时间 O(n), 空间 O(n)

from typing import List

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

class Solution:
    def flatten(self, root: TreeNode) -> None:
        """
        Do not return anything, modify root in-place instead.
        """
        def dfs(root):
            if not root:
                return None
            list_node.append(root)
            dfs(root.left)
            dfs(root.right)
        
        list_node = []
        dfs(root)
        list_node.append(None)
        for i in range(len(list_node)-1):
            list_node[i].left = None
            list_node[i].right = list_node[i+1]
        return list_node[0]

版本2 迭代与展开同步进行, 时间 O(n), 空间 O(1)

class Solution:
    def flatten(self, root: TreeNode) -> None:
        if not root:
            return None
        stack_node = []
        pre = None
        cur = root
        while cur or stack_node:
            if cur:
                pre = cur
                temp = cur.left
                cur.left = None
                stack_node.append(cur.right)
                cur = temp
            else:
                cur = stack_node.pop()
            pre.right = cur
        return root

二叉搜索树的遍历序列

验证二叉搜索树的后序遍历序列

LeetCode.剑指 Offer 33. 二叉搜索树的后序遍历序列

输入一个整数数组, 判断该数组是不是某二叉搜索树的后序遍历结果. 如果是则返回 true, 否则返回 false. 假设输入的数组的任意两个数字都互不相同. 
参考以下这颗二叉搜索树:
     5
    /    2   6
  /  1   3
输入: [1,6,3,2,5]
输出: false
输入: [1,3,2,6,5]
输出: true
class Solution:
    def verifyPostorder(self, postorder: List[int]) -> bool:
        if len(postorder) == 0:
            return True
        root_val = postorder[-1]
        i = 0
        while postorder[i] < root_val:
            i += 1
        j = i
        while postorder[j] > root_val:
            j += 1
        if j != len(postorder) - 1:
            return False
        left = True
        if i > 0:
            left = self.verifyPostorder(postorder[:i])
        right = True
        if i < j:
            right = self.verifyPostorder(postorder[i:-1])
        return left and right

前序遍历构造二叉搜索树

LeetCode.1008. 前序遍历构造二叉搜索树

返回与给定前序遍历 preorder 相匹配的二叉搜索树(binary search tree)的根结点
输入: [8,5,1,7,10,12]
输出: [8,5,10,1,7,null,12]
from typing import List

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

class Solution:
    def bstFromPreorder(self, preorder: List[int]) -> TreeNode:
        if len(preorder) == 0:
            return None
        root = TreeNode(preorder[0])
        id_right = 0
        while id_right < len(preorder) and preorder[id_right] <= root.val:
            id_right += 1
        root.left = self.bstFromPreorder(preorder[1:id_right])
        root.right = self.bstFromPreorder(preorder[id_right:])
        return root

另外一种方法是通过前序遍历与中序遍历构造二叉搜索树, 此时二叉搜索树的中序遍历就是树中所有的元素的值的升序排序.

LeetCode: 二叉树的遍历

标签:epo   null   repos   结果   构造二叉树   self   验证   ack   深度   

原文地址:https://www.cnblogs.com/funmore233/p/14610552.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!