二叉树试题(Python实现)

目录

1. 二叉树的层序遍历

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

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

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

5. 二叉树的前序遍历

6. 二叉树的中序遍历

7. 二叉树的后序遍历

8. 对称的二叉树

9. 合并二叉树

10. 二叉树的镜像

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

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

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

14. 升序数组 转 平衡二叉搜索树

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

16. 有多少个不同的二叉搜索树

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

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

19. 序列化二叉树

20. 重建二叉树

21. 输出二叉树的右视图


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. 二叉树的最大深度(层序遍历)

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. 按之字形顺序打印二叉树(层序遍历)

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. 二叉树中和为某一值的路径(层序遍历)

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. 对称的二叉树

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. 合并二叉树

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. 二叉树的镜像

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. 判断是不是二叉搜索树

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. 判断是不是完全二叉树

队列实现(层序遍历)

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. 判断是不是平衡二叉树

自顶向下(递归)

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. 升序数组 转 平衡二叉搜索树

递归实现

class Solution:
    def sortedArrayToBST(self , num: List[int]) -> TreeNode:
        if num is None or len(num) == 0:
            return None
        return self.func(num, 0, len(num)-1)
    
    def func(self, num, l, r):
        if l > r:
            return None
        if l == r:
            root = TreeNode(num[l])
            return root
        length = r - l + 1
        mid = l + length//2
        root = TreeNode(num[mid])
        root.left = self.func(num, l, mid-1)
        root.right = self.func(num, mid+1, r)
        return root

递归简化版

class Solution:
    def sortedArrayToBST(self , num: List[int]) -> TreeNode:
        if len(num) == 0:
            return None
        if len(num) == 1:
            return TreeNode(num[0])
        index = len(num)//2
        node = TreeNode(num[index])
        node.left = self.sortedArrayToBST(num[:index])
        node.right = self.sortedArrayToBST(num[index+1:])
        return node

栈模拟递归

class Solution:
    def sortedArrayToBST(self, num: List[int]) -> TreeNode:
        if num is None or len(num) == 0:
            return None
        # 保存结果(模拟栈)
        res = []
        # 保持左右分界点
        stack = []
        root = TreeNode(0)
        res.append(root)
        stack.append(0)
        stack.append(len(num)-1)
        while len(res) > 0:
            # 当前区间
            r = stack.pop()
            l = stack.pop()
            # 当前区间根节点位置
            mid = l + (r - l + 1)//2
            node = res.pop()
            node.val = num[mid]
            # 左区间,构造左子结点
            if l <= mid - 1:
                node.left = TreeNode(0)
                res.append(node.left)
                stack.append(l)
                stack.append(mid-1)
            # 右区间
            if r >= mid + 1:
                node.right = TreeNode(0)
                res.append(node.right)
                stack.append(mid+1)
                stack.append(r)
        return root

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

递归实现(中序遍历)

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

16. 有多少个不同的二叉搜索树

# 以j为头结点进行搜索,左子树有j-1个结点,右子树有i-j个结点
# 状态转移方程:i个结点的树个数==j个结点左子树个数*i-1-j个结点右子树个数

n = int(input())
dp = [0]*(n+1)
dp[0],dp[1] = 1,1
for i in range(2,n+1):
    for j in range(i):
        dp[i] += dp[j]*dp[i-j-1]
print(dp[n])

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

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

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

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

19. 序列化二叉树

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

20. 重建二叉树

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

21. 输出二叉树的右视图

层序遍历+哈希表

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)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值