leetcode(9)二叉树遍历系列题目

二叉树的种类

满二叉树

如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。
深度为k,有2^k-1个节点

完全二叉树

在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点

二叉搜索树

节点的值是有序的。

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值
  • 它的左、右子树也分别为二叉排序树

平衡二叉搜索树

又被称为AVL(Adelson-Velsky and Landis)树,且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

C++中map、set、multimap,multiset的底层实现都是平衡二叉搜索树,所以map、set的增删操作时间时间复杂度是logn,而unordered_map底层实现是哈希表。

二叉树的遍历方式

深度优先遍历:递归

144.二叉树的前序遍历
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        res = []

        def traversal(root):
            if not root:
                return
            res.append(root.val)
            traversal(root.left)
            traversal(root.right)
            
        traversal(root)
        return res
145.二叉树的后序遍历
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        res = []

        def traversal(root):
            if not root:
                return
            traversal(root.left)
            traversal(root.right)
            res.append(root.val)

        traversal(root)
        return res
94.二叉树的中序遍历
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        res = []

        def traversal(root):
            if not root:
                return
            traversal(root.left)
            res.append(root.val)
            traversal(root.right)
        
        traversal(root)
        return res

深度优先遍历:迭代(借助栈)

144.二叉树的前序遍历
class Solution:
    def preorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        # 根结点为空则返回空列表
        if not root:
            return []
        res = []
        stack = [root]
        while stack:
            node = stack.pop()
            # 中结点先处理
            res.append(node.val)
            # 右孩子先入栈
            if node.right:
                stack.append(node.right)
            # 左孩子后入栈
            if node.left:
                stack.append(node.left)
        return res
145.二叉树的后序遍历
class Solution:
    def postorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        res = []
        stack = [root]
        while stack:
            node = stack.pop()
            # 中结点先处理
            res.append(node.val)
            # 左孩子先入栈
            if node.left:
                stack.append(node.left)
            # 右孩子后入栈
            if node.right:
                stack.append(node.right)
        # 将最终的数组翻转    
        return res[::-1]

94.二叉树的中序遍历
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        res = []
        stack = []  # 不能提前将root结点加入stack中
        cur = root
        while cur or stack:
            # 先迭代访问最底层的左子树结点
            if cur:
                stack.append(cur)
                cur = cur.left
            else:
                # 到达最左结点后处理栈顶结点
                cur = stack.pop()
                res.append(cur.val)
                # 取栈顶元素右结点
                cur = cur.right
        return res

广度优先遍历(层序遍历):迭代(借助队列)

deque来自collections模块,不在力扣平台时,需要手动写入
'from collections import deque' 导入
deque相比list的好处是,list的pop(0)是O(n)复杂度,deque的popleft()是O(1)复杂度

102. 二叉树的层序遍历
class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res = []

        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            ans = []
            for _ in range(size):
                cur = que.popleft()
                ans.append(cur.val)
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
            res.append(ans)
            
        return res
103. 二叉树的锯齿形层序遍历

注意:与102. 二叉树的层序遍历 的区别是偶数层加一步反转即可

class Solution:
    def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res = []

        from collections import deque
        que = deque([root])

        flag = False
        while que:
            size = len(que)
            ans = []
            for _ in range(size):
                cur = que.popleft()
                ans.append(cur.val)
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
            if flag:
                ans = ans[::-1]  # 反转字符串
            flag = not flag
            res.append(ans)
        return res
107. 二叉树的层序遍历 II

注意:与102. 二叉树的层序遍历 的区别是最后加一步反转即可

class Solution:
    def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        if not root:
            return []
        res = []

        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            ans = []
            for _ in range(size):
                cur = que.popleft()
                ans.append(cur.val)
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
            res.append(ans)

        res.reverse()  # 加这一步反转
        return res
199. 二叉树的右视图

注意:与102. 二叉树的层序遍历 的区别是判断是否遍历到单层的最后一个元素,如果是,就放进result数组中,最后返回result就可以了。

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

        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            for i in range(size):
                cur = que.popleft()
                if i == size - 1:  # 判断是否是最后一个
                    res.append(cur.val)
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
        
        return res
637. 二叉树的层平均值

注意:与102. 二叉树的层序遍历 的区别是层序遍历的时候把一层求总和再取均值

class Solution:
    def averageOfLevels(self, root: Optional[TreeNode]) -> List[float]:
        if not root:
            return []
        res = []
        
        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            sum_ = 0
            for _ in range(size):
                cur = que.popleft()
                sum_ += cur.val  # 求和
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
            res.append(sum_ / size)  # 取平均
            
        return res
429. N 叉树的层序遍历

注意:与102. 二叉树的层序遍历 的区别是一个节点有多个孩子

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root:
            return []
        res = []

        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            ans = []
            for _ in range(size):
                cur = que.popleft()
                ans.append(cur.val)
                if cur.children:
                    que.extend(cur.children)  # 注意使用extend函数
            res.append(ans)
                
        return res
515. 在每个树行中找最大值

注意:与102. 二叉树的层序遍历 的区别是取每一行的最大值

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

        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            ans = []
            for _ in range(size):
                cur = que.popleft()
                ans.append(cur.val)
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
            res.append(max(ans))  # 将最大值存入
        
        return res
116. 填充每个节点的下一个右侧节点指针
117. 填充每个节点的下一个右侧节点指针 II

注意:与102. 二叉树的层序遍历 的区别是在单层遍历的时候让指针指向其下一个右侧节点,如果是该层最后一个节点,则跳出循环

class Solution:
    def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
        if not root:
            return root
        
        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            for i in range(size):
                cur = que.popleft()
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
                if i == size - 1:  # 如果是该层最后一个节点,则跳出循环
                    break
                cur.next = que[0]  # 让这个指针指向其下一个右侧节点
        return root
104. 二叉树的最大深度

注意:与102. 二叉树的层序遍历 的区别是最大的深度就是二叉树的层数,记录层数最后返回即可
递归写法:

class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:return 0
        return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1
class Solution:
    def maxDepth(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        res = 0
        
        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            for _ in range(size):
                cur = que.popleft()
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
            res += 1  #记录层数

        return res
111. 二叉树的最小深度

注意:与104. 二叉树的最大深度 的区别是只有当左右孩子都为空的时候,才说明遍历的最低点了。

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        res = 1  # 注意初始化为1

        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            for _ in range(size):
                cur = que.popleft()                
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
                if not cur.left and not cur.right:  # 左右节点都没有时
                    return res
            res += 1  # 记录层数
        return res
226. 翻转二叉树
递归法:前序遍历或后序遍历:
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return root
        
        self.invertTree(root.left)
        self.invertTree(root.right)
        # 处理中间节点放在前面或者后面都可以
        root.left, root.right = root.right, root.left
        return root
迭代法:深度优先遍历(前序遍历):
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return root
        
        stack = [root]
        while stack:
            node = stack.pop()
            node.left, node.right = node.right, node.left  #中
            if node.left:
                stack.append(node.left) #左(左右顺序好像不影响)
            if node.right:
                stack.append(node.right) #右
        return root
迭代法:广度优先遍历(层序遍历):
class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if not root:
            return root
        
        from collections import deque
        que = deque([root])

        while que:
            size = len(que)
            for _ in range(size):
                cur = que.popleft()
                cur.left, cur.right = cur.right, cur.left
                if cur.left:
                    que.append(cur.left)
                if cur.right:
                    que.append(cur.right)
        return root
posted @ 2022-05-13 17:39  YTT77  阅读(47)  评论(0编辑  收藏  举报