返回

细品力扣965:二叉树的本质与单值二叉树的巧妙构造

前端

二叉树的本质

二叉树是一种特殊的树形数据结构,其中每个结点最多只有两个子结点,分别称为左子结点和右子结点。二叉树的结构非常适合用于表示具有层次关系的数据,例如文件系统、组织结构图等。

二叉树有许多不同的种类,其中最常见的是二叉搜索树(Binary Search Tree,简称 BST)。BST 是一种有序二叉树,其中每个结点的值都大于其左子结点的值,而小于其右子结点的值。BST 具有很高的查找效率,是许多算法的基础数据结构。

单值二叉树

单值二叉树是一种特殊的二叉树,其中每个结点的值都相同。单值二叉树的构建方法非常简单,只需将所有结点的值都设置为相同的值即可。

例如,以下二叉树就是一个单值二叉树:

        5
      /   \
     5     5
    / \   / \
   5   5 5   5

算法步骤

为了判断一棵二叉树是否为单值二叉树,我们可以使用以下递归算法:

def is_unival_tree(root):
  """
  判断一棵二叉树是否为单值二叉树

  参数:
    root: 二叉树的根结点

  返回:
    True 如果二叉树是单值二叉树,否则返回 False
  """

  # 如果二叉树为空,则它是单值二叉树
  if root is None:
    return True

  # 如果二叉树只有一个结点,则它是单值二叉树
  if root.left is None and root.right is None:
    return True

  # 如果二叉树的左子树和右子树都是单值二叉树,并且二叉树的根结点的值与左子树和右子树的根结点的值相等,则二叉树是单值二叉树
  if is_unival_tree(root.left) and is_unival_tree(root.right) and root.val == root.left.val and root.val == root.right.val:
    return True

  # 否则,二叉树不是单值二叉树
  else:
    return False

示例代码

from typing import Optional

class TreeNode:
  def __init__(self, val: int, left: Optional['TreeNode'] = None, right: Optional['TreeNode'] = None):
    self.val = val
    self.left = left
    self.right = right

def is_unival_tree(root: Optional[TreeNode]) -> bool:
  """
  判断一棵二叉树是否为单值二叉树

  参数:
    root: 二叉树的根结点

  返回:
    True 如果二叉树是单值二叉树,否则返回 False
  """

  # 如果二叉树为空,则它是单值二叉树
  if root is None:
    return True

  # 如果二叉树只有一个结点,则它是单值二叉树
  if root.left is None and root.right is None:
    return True

  # 如果二叉树的左子树和右子树都是单值二叉树,并且二叉树的根结点的值与左子树和右子树的根结点的值相等,则二叉树是单值二叉树
  if is_unival_tree(root.left) and is_unival_tree(root.right) and root.val == root.left.val and root.val == root.right.val:
    return True

  # 否则,二叉树不是单值二叉树
  else:
    return False


# 测试
root = TreeNode(1)
root.left = TreeNode(1)
root.right = TreeNode(1)
root.left.left = TreeNode(1)
root.left.right = TreeNode(1)
root.right.left = TreeNode(1)
root.right.right = TreeNode(1)

print(is_unival_tree(root))  # 输出:True

root = TreeNode(2)
root.left = TreeNode(2)
root.right = TreeNode(2)
root.left.left = TreeNode(5)
root.left.right = TreeNode(2)
root.right.left = TreeNode(2)
root.right.right = TreeNode(2)

print(is_unival_tree(root))  # 输出:False

图解

以下图解演示了算法的执行过程:

        5
      /   \
     5     5
    / \   / \
   5   5 5   5

调用 is_unival_tree(root)

检查 root 的值是否与 leftright 的值相等

是,继续递归检查 leftright

调用 is_unival_tree(root.left)

检查 root.left 的值是否与 left.leftleft.right 的值相等

是,继续递归检查 left.leftleft.right

调用 is_unival_tree(root.left.left)

检查 root.left.left 的值是否与 left.left.leftleft.left.right 的值相等

是,继续递归检查 left.left.leftleft.left.right

调用 is_unival_tree(root.left.left.left)

检查 root.left.left.left 的值是否与 left.left.left.leftleft.left.left.right 的值相等

是,继续递归检查 left.left.left.leftleft.left.left.right

调用 is_unival_tree(root.left.left.left.left)

检查 root.left.left.left.left 的值是否与 left.left.left.left.leftleft.left.left.left.right 的值相等

是,继续递归检查 left.left.left.left.leftleft.left.left.left.right

调用 is_unival_tree(root.left.left.left.left.left)

检查 root.left.left.left.left.left 的值是否与 left.left.left.left.left.leftleft.left.left.left.left.right 的值相等

是,继续递归检查 left.left.left.left.left.leftleft.left.left.left.left.right

调用 is_unival_tree(root.left.left.left.left.left.left)

检查 root.left.left.left.left.left.left 的值是否与 left.left.left.left.left.left.left.leftleft.left.left.left.left.left.left.right 的值相等

是,继续递归检查 left.left.left.left.left.left.left.leftleft.left.left.left.left.left.left.right

调用 is_unival_tree(root.left.left.left.left.left.left.left.left)

检查 root.left.left.left.left.left.left.left.left 的值是否与 left.left.left.left.left.left.left.left.left.leftleft.left.left.left.left.left.left.left.left.right 的值相等

是,继续递归检查 left.left.left.left.left.left.left.left.left.leftleft.left.left.left.left.left.left.left.left.right

调用 is_unival_tree(root.left.left.left.left.left.left.left.left.left.left)

检查 root.left.left.left.left.left.left.left.left.left.left.left 的值是否与 left.left.left.left.left.left.left.left.left.left.left.left.leftleft.left.left.left.left.left.left.left.left.left.left.left.right 的值相等

是,继续递归检查 left.left.left.left.left.left.left.left.left.left.left.left.left.left