二叉树试题(Python实现)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

1. 二叉树的层序遍历

 2. 二叉树的最大深度层序遍历

3. 按之字形顺序打印二叉树层序遍历变形

 4. 二叉树中和为某一值的路径层序遍历变形

5. 二叉树的前序遍历

6. 二叉树的中序遍历

7. 二叉树的后序遍历

8. 对称的二叉树

9. 合并二叉树

10. 二叉树的镜像

11. 判断是不是二叉搜索树

12. 判断是不是完全二叉树

13. 判断是不是平衡二叉树

14. 二叉搜索树的最近公共祖先

15. 两个节点的最近公共祖先

16. 二叉搜索树 转 双向链表

17. 序列化二叉树

18. 重建二叉树

19. 输出二叉树的右视图

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

1. 二叉树的层序遍历

非递归队列实现

import queue
class Solution:
    def levelOrder(self , root: TreeNode) -> List[List[int]]:
        res = []
        if root is None: return res
        # 队列实现
        q = queue.Queue()
        q.put(root)
        while not q.empty():
            now = []
            n = q.qsize()
            for _ in range(n):
                cur = q.get()
                now.append(cur.val)
                if cur.left: q.put(cur.left)
                if cur.right: q.put(cur.right)
            res.append(now)
        return res

递归使用深度depth记录

class Solution:
    res = []
    def traverse(self, root: TreeNode, depth: int):
        if root:
            # 检查当前深度
            if len(self.res) < depth:
                now = []
                self.res.append(now)
                now.append(root.val)
            else:
                now = self.res[depth-1]
                now.append(root.val)
        else: return
        # 递归左右子树深度+1
        self.traverse(root.left, depth + 1)
        self.traverse(root.right, depth + 1)
    
    def levelOrder(self , root: TreeNode) -> List[List[int]]:
        if root is None: return self.res
        self.traverse(root, 1)
        return self.res

 2. 二叉树的最大深度层序遍历

二叉树的最大深度_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    def maxDepth(self , root: TreeNode) -> int:
        if root is None: return 0
        return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

非递归队列实现

import queue
class Solution:
    def maxDepth(self , root: TreeNode) -> int:
        res = 0
        if root is None: return res
        q = queue.Queue()
        q.put(root)
        while not q.empty():
            n = q.qsize()
            for _ in range(n):
                cur = q.get()
                if cur.left: q.put(cur.left)
                if cur.right: q.put(cur.right)
            res += 1
        return res

3. 按之字形顺序打印二叉树层序遍历变形

按之字形顺序打印二叉树_牛客题霸_牛客网 (nowcoder.com)

import queue
class Solution:
    def Print(self , pRoot: TreeNode) -> List[List[int]]:
        res = []
        if pRoot is None: return res
        q = queue.Queue()
        q.put(pRoot)
        flag = True
        while not q.empty():
            now = []
            flag = not flag
            n = q.qsize()
            for _ in range(n):
                cur = q.get()
                now.append(cur.val)
                if cur.left: q.put(cur.left)
                if cur.right: q.put(cur.right)
            # 偶数行反转
            if flag:
                now = now[::-1]
            res.append(now)
        return res

 4. 二叉树中和为某一值的路径层序遍历变形

二叉树中和为某一值的路径(一)_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    def hasPathSum(self , root: TreeNode, sum: int) -> bool:
        if root is None: return False
        if root.left is None and root.right is None and root.val == sum: return True
        return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right, sum-root.val)

非递归栈实现

class Solution:
    def hasPathSum(self , root: TreeNode, sum: int) -> bool:
        if root is None: return False
        # 模拟栈
        s = []
        s.append((root, root.val))
        while len(s):
            cur = s[-1]
            s.pop()
            if not cur[0].left and not cur[0].right and cur[1] == sum:
                return True
            if cur[0].left:
                s.append((cur[0].left, cur[1] + cur[0].left.val))
            if cur[0].right:
                s.append((cur[0].right, cur[1] + cur[0].right.val))
        return False

5. 二叉树的前序遍历

class Solution:
    # 递归前序遍历
    def preorder(self, ls: List[int], root: TreeNode):
        if root is None: return
        ls.append(root.val)
        self.preorder(ls, root.left)
        self.preorder(ls, root.right)
    def preorderTraversal(self , root: TreeNode) -> List[int]:
        ls = []
        self.preorder(ls, root)
        return ls

非递归栈实现

class Solution:
    def preorderTraversal(self , root: TreeNode) -> List[int]:
        res = []
        if root is None: return res
        # 模拟栈
        s = []
        s.append(root)
        while s:
            cur = s[-1]
            # 拿到之后pop走
            s.pop()
            res.append(cur.val)
            # 后进先出先放右节点再放左节点
            if cur.right: s.append(cur.right)
            if cur.left: s.append(cur.left)
        return res

6. 二叉树的中序遍历

class Solution:
    # 递归中序遍历
    def inorder(self, ls: List[int], root: TreeNode):
        if root is None: return
        self.inorder(ls, root.left)
        ls.append(root.val)
        self.inorder(ls, root.right)
    def inorderTraversal(self , root: TreeNode) -> List[int]:
        ls = []
        self.inorder(ls, root)
        return ls

非递归栈实现

class Solution:
    def inorderTraversal(self , root: TreeNode) -> List[int]:
        res = []
        if root is None: return res
        # 模拟栈
        s = []
        while root or s:
            # 将根节点存入栈走到最左子节点
            while root:
                s.append(root)
                root = root.left
            # 获得最左子节点
            cur = s[-1]
            s.pop()
            res.append(cur.val)
            # 走到右节点
            root = cur.right
        return res

7. 二叉树的后序遍历

class Solution:
    # 递归后序遍历
    def postorder(self, ls: List[int], root: TreeNode):
        if root is None: return
        self.postorder(ls, root.left)
        self.postorder(ls, root.right)
        ls.append(root.val)
    def postorderTraversal(self , root: TreeNode) -> List[int]:
        ls = []
        self.postorder(ls, root)
        return ls

非递归栈实现

class Solution:
    def postorderTraversal(self , root: TreeNode) -> List[int]:
        res = []
        if root is None: return res
        # 模拟栈
        s = []
        # 记录访问过的元素
        pre = None
        while root or s:
            # 将根节点存入栈走到最左子节点
            while root:
                s.append(root)
                root = root.left
            # 获得最左子节点
            cur = s[-1]
            s.pop()
            # 如果右子树为空或已访问过
            if cur.right is None or cur.right is pre:
                res.append(cur.val)
                pre = cur
            else:
                s.append(cur)
                root = cur.right
        return res

8. 对称的二叉树

对称的二叉树_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    # 递归比较两节点是否对称
    def cmp(self, root1: TreeNode, root2: TreeNode) -> bool:
        if root1 is None and root2 is None: return True
        if root1 is None or root2 is None or root1.val != root2.val: return False
        return self.cmp(root1.left, root2.right) and self.cmp(root1.right, root2.left)
    def isSymmetrical(self , pRoot: TreeNode) -> bool:
        return self.cmp(pRoot, pRoot)

非递归双队列实现

import queue
class Solution:
    def isSymmetrical(self , pRoot: TreeNode) -> bool:
        if pRoot is None: return True
        q1 = queue.Queue()
        q2 = queue.Queue()
        q1.put(pRoot.left)
        q2.put(pRoot.right)
        while not q1.empty() and not q2.empty():
            left = q1.get()
            right = q2.get()
            # 都为空则继续
            if left is None and right is None:
                continue
            # 只有一侧为空 或 val不相等则不对称
            if left is None or right is None or left.val != right.val:
                return False
            q1.put(left.left)
            q1.put(left.right)
            q2.put(right.right)
            q2.put(right.left)
        return True

9. 合并二叉树

合并二叉树_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    def mergeTrees(self , t1: TreeNode, t2: TreeNode) -> TreeNode:
        if t1 is None: return t2
        if t2 is None: return t1
        head = TreeNode(t1.val + t2.val)
        head.left = self.mergeTrees(t1.left, t2.left)
        head.right = self.mergeTrees(t1.right, t2.right)
        return head

非递归三队列实现

import queue
class Solution:
    def mergeTrees(self , t1: TreeNode, t2: TreeNode) -> TreeNode:
        if t1 is None: return t2
        if t2 is None: return t1
        head = TreeNode(t1.val + t2.val)
        q = queue.Queue()
        q1 = queue.Queue()
        q2 = queue.Queue()
        q.put(head)
        q1.put(t1)
        q2.put(t2)
        while not q1.empty() and not q2.empty():
            cur, cur1, cur2 = q.get(), q1.get(), q2.get()
            l1, r1, l2, r2 = cur1.left, cur1.right, cur2.left, cur2.right
            if l1 or l2:
                if l1 and l2:
                    left = TreeNode(l1.val + l2.val)
                    cur.left = left
                    q.put(left)
                    q1.put(l1)
                    q2.put(l2)
                else:
                    cur.left = l1 if l1 else l2
            if r1 or r2:
                if r1 and r2:
                    right = TreeNode(r1.val + r2.val)
                    cur.right = right
                    q.put(right)
                    q1.put(r1)
                    q2.put(r2)
                else:
                    cur.right = r1 if r1 else r2
        return head

10. 二叉树的镜像

二叉树的镜像_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    def Mirror(self , pRoot: TreeNode) -> TreeNode:
        if pRoot is None: return None
        left = self.Mirror(pRoot.left)
        right = self.Mirror(pRoot.right)
        pRoot.left, pRoot.right = right, left
        return pRoot

非递归栈实现

class Solution:
    def Mirror(self , pRoot: TreeNode) -> TreeNode:
        if pRoot is None: return None
        # 模拟栈
        s = []
        s.append(pRoot)
        while s:
            cur = s[-1]
            s.pop()
            if cur.left:
                s.append(cur.left)
            if cur.right:
                s.append(cur.right)
            # 直接交换树节点左右子树
            cur.left, cur.right = cur.right, cur.left
        return pRoot

11. 判断是不是二叉搜索树

判断是不是二叉搜索树_牛客题霸_牛客网 (nowcoder.com)

import sys
class Solution:
    # 最值记录
    pre = -sys.maxsize -1
    def isValidBST(self , root: TreeNode) -> bool:
        if root is None: return True
        # 左子树
        if not self.isValidBST(root.left):
            return False
        if root.val <= self.pre:
            return False
        # 更新最值
        self.pre = root.val
        if not self.isValidBST(root.right):
            return False
        return True

非递归栈实现中序遍历

class Solution:
    def isValidBST(self , root: TreeNode) -> bool:
        s = []
        res = []
        while root or s:
            # 走到左子节点
            while root:
                s.append(root)
                root = root.left
            root = s[-1]
            s.pop()
            res.append(root.val)
            root = root.right
        # 检查中序遍历结果即可
        for i in range(1, len(res)):
            if res[i -1] > res[i]:
                return False
        return True

12. 判断是不是完全二叉树

判断是不是完全二叉树_牛客题霸_牛客网 (nowcoder.com)

队列实现层序遍历

import queue
class Solution:
    def isCompleteTree(self , root: TreeNode) -> bool:
        if root is None: return True
        q = queue.Queue()
        q.put(root)
        flag = False
        while not q.empty():
            size = q.qsize()
            for _ in range(size):
                cur = q.get()
                if cur is None:
                    flag = True
                else:
                    if flag: return False
                    q.put(cur.left)
                    q.put(cur.right)
        return True

13. 判断是不是平衡二叉树

判断是不是平衡二叉树_牛客题霸_牛客网 (nowcoder.com)

自顶向下递归

class Solution:
    # 计算深度
    def depth(self, root: TreeNode) -> int:
        if root is None: return 0
        return max(self.depth(root.left), self.depth(root.right)) + 1

    def IsBalanced_Solution(self, pRoot: TreeNode) -> bool:
        if pRoot is None: return True
        left = self.depth(pRoot.left)
        right = self.depth(pRoot.right)
        # 当前节点左右子树深度是否小于1
        if abs(left-right) > 1: return False
        # 检查左右子树是否都平衡
        return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)

自底向上

class Solution:
    # 计算深度
    def depth(self, root: TreeNode) -> int:
        if root is None: return 0
        # 左子树
        left = self.depth(root.left)
        if left == -1: return -1
        # 右子树
        right = self.depth(root.right)
        if right == -1: return -1
        return -1 if abs(left - right) > 1 else max(left,right) + 1
    def IsBalanced_Solution(self , pRoot: TreeNode) -> bool:
        if pRoot is None: return True
        return self.depth(pRoot) != -1

14. 二叉搜索树的最近公共祖先

二叉搜索树的最近公共祖先_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    def lowestCommonAncestor(self , root: TreeNode, p: int, q: int) -> int:
        if root is None: return -1
        if (p >= root.val and q <= root.val) or (p <= root.val and q >= root.val):
            return root.val
        elif p <= root.val and q <= root.val:
            return self.lowestCommonAncestor(root.left, p, q)
        else:
            return self.lowestCommonAncestor(root.right, p, q)

非递归搜索路径比较

class Solution:
    # 得到搜索路径
    def getPath(self, root: TreeNode, target: int) -> List[int]:
        res = []
        while root.val != target:
            res.append(root.val)
            if target < root.val:
                root = root.left
            else:
                root = root.right
        res.append(root.val)
        return res
    def lowestCommonAncestor(self , root: TreeNode, p: int, q: int) -> int:
        # 求根节点到两个节点的路径
        path_p = self.getPath(root, p)
        path_q = self.getPath(root, q)
        for i in range(min(len(path_p), len(path_q))):
            # 一直走到路径不相等时结束循环
            if path_p[i] == path_q[i]:
                res = path_p[i]
            else:
                break
        return res

15. 两个节点的最近公共祖先

在二叉树中找到两个节点的最近公共祖先_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    def lowestCommonAncestor(self , root: TreeNode, o1: int, o2: int) -> int:
        if root is None: return -1
        if root.val == o1 or root.val == o2:
            return root.val
        left = self.lowestCommonAncestor(root.left, o1, o2)
        right = self.lowestCommonAncestor(root.right, o1, o2)
        if left == -1: return right
        if right == -1: return left
        # 否则是当前节点
        return root.val

非递归深度优先搜索dfs

class Solution:
    # 记录是否找到o的路径
    flag = False
    # 计算根节点到目标节点的路径
    def dfs(self, root: TreeNode, path: List[int], o: int):
        if self.flag or root is None: return
        path.append(root.val)
        if root.val == o:
            self.flag = True
            return
        self.dfs(root.left, path, o)
        self.dfs(root.right, path, o)
        if self.flag:
            return
        # 否则该子树没有回溯
        path.pop()

    def lowestCommonAncestor(self , root: TreeNode, o1: int, o2: int) -> int:
        path1, path2 = [], []
        self.dfs(root, path1, o1)
        # 重置flag
        self.flag = False
        self.dfs(root, path2, o2)
        res = None
        # 一直走到路径不相等时结束循环
        for i in range(min(len(path1), len(path2))):
            if path1[i] == path2[i]:
                res = path1[i]
            else:
                break
        return res

16. 二叉搜索树 转 双向链表

二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com)

递归实现中序遍历

class Solution:
    head = None
    pre = None
    def Convert(self , pRootOfTree ):
        if pRootOfTree is None: return None
        # 递归找到最小值
        self.Convert(pRootOfTree.left)
        # 头节点初始化
        if self.pre is None:
            self.head = pRootOfTree
            self.pre = pRootOfTree
        # 当前节点与上一点建立连接
        else:
            self.pre.right = pRootOfTree
            pRootOfTree.left = self.pre
            self.pre = pRootOfTree
        self.Convert(pRootOfTree.right)
        return self.head

非递归实现

class Solution:
    def Convert(self , pRootOfTree ):
        if pRootOfTree is None: return None
        # 模拟栈
        s = []
        head = None
        pre = None
        # 标记最小值最左子节点
        flag = True
        while pRootOfTree or s:
            while pRootOfTree:
                s.append(pRootOfTree)
                pRootOfTree = pRootOfTree.left
            pRootOfTree = s[-1]
            s.pop()
            # 头节点初始化
            if flag:
                head = pRootOfTree
                pre = head
                flag = False
            else:
                pre.right = pRootOfTree
                pRootOfTree.left = pre
                pre = pRootOfTree
            pRootOfTree = pRootOfTree.right
        return head

17. 序列化二叉树

序列化二叉树_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    def __init__(self) -> None:
        self.index = 0
        self.s = ""
    
    # 序列化
    def Serialize(self, root):
        # 空节点 #
        if root is None:
            self.s += '#'
            return self.s
        # 根节点 !
        self.s += (str)(root.val) + '!'
        # 左子树
        self.Serialize(root.left)
        # 右子树
        self.Serialize(root.right)
        return self.s

    # 反序列化
    def Deserialize(self, s):
        if s == "#": return None
        if self.index >= len(s) or s[self.index] == "#":
            self.index += 1
            return None
        val = 0
        while s[self.index] != '!' and self.index != len(s):
            val = val*10 + (int)(s[self.index])
            self.index += 1
        root = TreeNode(val)
        if self.index == len(s):
            return root
        else:
            self.index += 1
        root.left = self.Deserialize(s)
        root.right = self.Deserialize(s)
        return root

18. 重建二叉树

重建二叉树_牛客题霸_牛客网 (nowcoder.com)

class Solution:
    def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
        n = len(pre)
        m = len(vin)
        if n == 0 or m == 0: return None
        root = TreeNode(pre[0])
        for i in range(n):
            # 在中序遍历中找到前序遍历的根节点
            if pre[0] == vin[i]:
                # 左子树前序
                leftpre = pre[1:i+1]
                # 左子树中序
                leftvin = vin[:i]
                # 左子树
                root.left = self.reConstructBinaryTree(leftpre, leftvin)
                # 右子树前序
                rightpre = pre[i+1:]
                # 右子树中序
                rightvin = vin[i+1:]
                root.right = self.reConstructBinaryTree(rightpre, rightvin)
                break
        return root

非递归栈实现

class Solution:
    def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
        n = len(pre)
        m = len(vin)
        if n == 0 or m == 0: return None
        s = []
        # 根节点
        root = TreeNode(pre[0])
        cur = root
        j = 0
        for i in range(1, n):
            if cur.val != vin[j]:
                cur.left = TreeNode(pre[i])
                s.append(cur)
                cur = cur.left
            else:
                j += 1
                while s and s[-1].val == vin[j]:
                    cur = s[-1]
                    s.pop()
                    j += 1
                cur.right = TreeNode(pre[i])
                cur = cur.right
        return root

19. 输出二叉树的右视图

输出二叉树的右视图_牛客题霸_牛客网 (nowcoder.com)

层序遍历+哈希表

from collections import defaultdict
import queue
class Solution:
    index = defaultdict(int)
    # 建树函数
    # 四个int参数分别是前序最左节点下标前序最右节点下标
    # 中序最左节点下标中序最右节点坐标
    def buildTree(self, xianxu: List[int], l1: int, r1: int, zhongxu: List[int], l2: int, r2:int) -> TreeNode:
        if l1 > r1 or l2 > r2:
            return None
        # 前序遍历中的第一个节点就是根节点
        xianxu_root = l1 
        # 在中序遍历中定位根节点
        zhongxu_root = self.index[xianxu[xianxu_root]] 
        root = TreeNode(xianxu[xianxu_root])
        # 得到左子树中的节点数目
        leftsize = zhongxu_root - l2 
        root.left = self.buildTree(xianxu, l1 + 1, l1 + leftsize, zhongxu, l2, zhongxu_root - 1)
        root.right = self.buildTree(xianxu, l1 + leftsize + 1, r1, zhongxu, zhongxu_root + 1, r2)
        return root
    
    #层次遍历
    def rightSideView(self, root: TreeNode) -> List[int]:
        res = []
        q = queue.Queue()
        q.put(root)
        while not q.empty():
            #队列中的大小即是这一层的节点树
            size = q.qsize()
            while size:
                size -= 1
                temp = q.get()
                if temp.left:
                    q.put(temp.left)
                if temp.right:
                    q.put(temp.right)
                #最右元素
                if size == 0:
                    res.append(temp.val)
        return res
    
    def solve(self , xianxu: List[int], zhongxu: List[int]) -> List[int]:
        res = []
        # 空节点
        if len(xianxu) == 0: 
            return res
        for i in range(len(xianxu)):
            self.index[zhongxu[i]] = i
        # 建树
        root = self.buildTree(xianxu, 0, len(xianxu) - 1, zhongxu, 0, len(zhongxu) - 1)
        # 找每一层最右边的节点
        return self.rightSideView(root)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: python