关于二叉树的相关题目

\qquad 二叉树在数据结构中具有十分重要的作用,很多算法题都使用到树的思想。将复杂的算法题转化为简单子问题,并用树的形式表示,可以直观理解划分的过程,有利于分析和写出算法程序。比如:对于递归问题,就可以转化成树的形式,将树的叶节点作为终止条件,将树的生成过程作为迭代公式,根据题目要求使用先序、中序、后序遍历,下面总结有关二叉树的相关题目,二叉树的题目普遍可以用递归迭代的方式来解:

首先写出二叉树的结构:

class TreeNode:
	def __init(self, x):
		self.val = x
       self.left = None
       self.right = None
1、求二叉树的最大深度
def max_depth(self, node):
    """
    求二叉树的最大深度
    """
    if node is None:
        return 0

    left = self.max_depth(node.left)
    right = self.max_depth(node.right)

    return max(left, right) + 1
2、求二叉树的最小深度
def min_depth(self, node):
    """
    求二叉树的最小深度
    """
    if node is None:
        return 0

    left = self.min_depth(node.left)
    right = self.min_depth(node.right)

    return min(left, right) + 1
3、求二叉树中节点的个数
def node_count(self, node):
    """
    求二叉树中节点的个数
    """
    if node is None:
        return 0

    left = self.node_count(node.left)
    right = self.node_count(node.right)

    return left + right + 1
4、求二叉树中叶子节点的个数
 def leaf_node_count(self, node):
        """
        求二叉树中叶子节点的个数
        """
        if node is None:
            return 0

        if node.left is None and node.right is None:
            return 1

        left = self.leaf_node_count(node.left)
        right = self.leaf_node_count(node.right)

        return left + right
5、求二叉树中第k层节点的个数
def k_level_count(self, node, k):
    """
    求二叉树中第k层节点的个数
    """
    if k < 1 or node is None:
        return 0

    if k == 1:
        return 1

    left = self.k_level_count(node.left, k-1)
    right = self.k_level_count(node.right, k-1)

    return left + right
6、后序遍历的应用:判断二叉树是否是平衡二叉树
"""
使用后序遍历,每个节点只遍历一次,效率高
"""
def is_balance_binary_tree(self, node):
    """
    判断二叉树是否是平衡二叉树
    """
    return self.max_depth2(node) != -1

def max_depth2(self, node):
    """
    检查树是否平衡
    """
    if node is None:
        return 0

    left = self.max_depth2(node.left)
    right = self.max_depth2(node.right)
    if left == -1 or right == -1 or math.fabs(left - right) > 1:
        return -1

    return max(left, right) + 1
7、层次遍历的应用:判断二叉树是否是完全二叉树
@staticmethod
def is_complete_binary_tree(node):
    """
    判断二叉树是否是完全二叉树:层次遍历,如果一个节点缺少孩子,则剩下的节点都应该没有孩子。
    """
    if node is None:
        return True

    _queue = queue.Queue()
    _queue.put(node)
    has_no_child = False
    result = True
    while not _queue.empty():
        current_node = _queue.get()
        if not has_no_child:
            if current_node.left is not None and current_node.right is not None:
                _queue.put(current_node.left)
                _queue.put(current_node.right)
            elif current_node.left is None and current_node.right is not None:
                result = False
                break
            elif current_node.left is not None and current_node.right is None:
                _queue.put(current_node.left)
                has_no_child = True
            else:
                has_no_child = True
        else:
            if current_node.left is not None or current_node.right is not None:
                result = False
                break
    return result
8、两个二叉树是否完全相同
def is_common_tree(self, node1, node2):
    """
    两个二叉树是否完全相同
    """
    if node1 is None and node2 is None:
        return True
    elif node1 is None or node2 is None:
        return False

    if node1.val != node2.val:
        return False

    left = self.is_common_tree(node1.left, node2.left)
    right = self.is_common_tree(node1.right, node2.right)

    return left and right
9、两个二叉树是否互为镜像
def is_mirror(self, node1, node2):
    """
    两个二叉树是否互为镜像
    """
    if node1 is None and node2 is None:
        return True
    elif node1 is None or node2 is None:
        return False

    if node1.val != node2.val:
        return False

    left = self.is_mirror(node1.left, node2.right)
    right = self.is_mirror(node1.right, node2.left)

    return left and right
10、翻转二叉树 or 镜像二叉树
def mirror_tree_node(self, node):
    """
    翻转二叉树 or 镜像二叉树
    """
    if node is None:
        return None

    left = self.mirror_tree_node(node.left)
    right = self.mirror_tree_node(node.right)

    # 每次都新建节点,不然会修改原始链表
    new_node = TreeNode(node.val)
    new_node.left = right
    new_node.right = left
    return new_node
11、二叉树的先序遍历(应用见No.15)
def pre_order(self, node):
    """
    二叉树的先序遍历
    """
    # result存放先序遍历结果
    result = []
    self.pre(node, result)
    return result

def pre(self, node, result):
    if node is None:
        return

    result.append(node.val)
    self.pre(node.left, result)
    self.pre(node.right, result)
12、二叉树的中序遍历(应用见No.16)
def in_order(self, node):
    """
    二叉树的中序遍历
    """
    result = []
    self.inside(node, result)
    return result

def inside(self, node, result):
    if node is None:
        return

    self.inside(node.left, result)
    result.append(node.val)
    self.inside(node.right, result)
13、二叉树的后序遍历(应用见No.6)
def post_order(self, node):
    """
    二叉树的后序遍历
    """
    result = []
    self.post(node, result)
    return result

def post(self, node, result):
    if node is None:
        return

    self.post(node.left, result)
    self.post(node.right, result)
    result.append(node.val)
14、二叉树的层次遍历(应用见No.7)
@staticmethod
def level_order(node):
    """
    二叉树的层次遍历
    """
    if node is None:
        return

    result = []
    _queue = queue.Queue()
    _queue.put(node)
    while not _queue.empty():
        current_node = _queue.get()
        result.append(current_node.val)
        if current_node.left is not None:
            _queue.put(current_node.left)
        if current_node.right is not None:
            _queue.put(current_node.right)
    return result
15、二叉树先序遍历的应用:输入一个二叉树和一个整数,打印出二叉树中节点值的和等于输入整数所有的路径(本例展示了如何输出满足条件的路径)
class Solution:
	def __init__(self):
        self.result = []
        
	def find_path(self, node, sum):
	    """输入一个二叉树和一个整数,打印出二叉树中节点值的和等于输入整数所有的路径"""
	    if node is None:
	        return
	
	    stack = []
	    path_sum = 0
	
	    self.find_sum_core(node, sum, stack, path_sum)
	
	def find_sum_core(self, node, sum, stack, path_sum):
	    stack.append(node.val)
	    path_sum += node.val
	
	    if node.left is None and node.right is None:
	        if path_sum == sum:
	            self.result.append(copy.deepcopy(stack))
	
	    if node.left is not None:
	        self.find_sum_core(node.left, sum, stack, path_sum)
	
	    if node.right is not None:
	        self.find_sum_core(node.right, sum, stack, path_sum)
	
	    stack.pop(-1)

缓存数组stack中添加路径节点,在满足终止条件返回父节点时,需要将当前节点从缓存中弹出,恢复现场(类似于递归,这里需要手动恢复)。

应用:
一只青蛙一次可以跳3级、4级或5级台阶,每一级台阶使用不同数量的石子组成,例如:数组[0, 3, 1, 3, 4, 1, 5, 6, 7]表示第一级台阶由3个石子组成,第二级台阶由1个石子组成,求青蛙从0的位置跳到最后一级台阶经过的最少石子的

import copy

class Solution:
    def __init__(self):
        self.path = []
        self.path_sum = []

    def get_minimum_stones(self, road_stone_list):
        length = len(road_stone_list)

        path = []
        path_sum = 0

        return self.get_minimum_stones_core(road_stone_list, path, path_sum, length-1)

    def get_minimum_stones_core(self, data, path, path_sum, n):
        path.append(data[n])
        path_sum += data[n]

        if 3 <= n <= 5:
            self.path.append(copy.deepcopy(path))
            self.path_sum.append(path_sum)

        if n > 3:
            self.get_minimum_stones_core(data, path, path_sum, n - 3)
        if n > 4:
            self.get_minimum_stones_core(data, path, path_sum, n - 4)
        if n > 5:
            self.get_minimum_stones_core(data, path, path_sum, n - 5)

        path.pop(-1)


if __name__ == '__main__':
    data = [0, 3, 1, 3, 4, 1, 5, 6, 7]

    S = Solution()
    S.get_minimum_stones(data)
    print("所有可行的路径:", S.path)
    print("路径的长度:", S.path_sum)
    # 取其中一个最小值
    print("最短路径:", S.path[S.path_sum.index(min(S.path_sum))])

输出结果:

所有可行的路径: [[7, 1], [7, 4], [7, 3]]
路径的长度: [8, 11, 10]
最短路径: [7, 1]
16、中序遍历的应用:二叉搜索树的第k个结点
"""

题目:给定一棵二叉搜索树,请找出其中的第k大的结点。

思路:

本题参考二叉搜索树的中序遍历,先找右子树,再找左子树,最终可以得到从大到小的输出。

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

class Solution:
    def find_kth_node(self, root, k):
        if root is None or k <= 0:
            return

        kth = [0]

        self.find_kth_node_core(root, k, kth)

    def find_kth_node_core(self, node, k, kth):
        if node is None or k < 0:
            return

        self.find_kth_node_core(node.right, k, kth)
        
        kth[0] += 1
        if kth[0] == k:
            print("二叉搜索树中第 %s 大的数:%s" % (k, node.val))
            
        self.find_kth_node_core(node.left, k, kth)
      
if __name__ == '__main__':
    node1 = TreeNode(5)
    node2 = TreeNode(3)
    node3 = TreeNode(7)
    node4 = TreeNode(2)
    node5 = TreeNode(4)
    node6 = TreeNode(6)
    node7 = TreeNode(8)

    node1.left = node2
    node1.right = node3
    node2.left = node4
    node2.right = node5
    node3.left = node6
    node3.right = node7

    S = Solution()
    S.find_kth_node(node1, 6)

输出:

二叉搜索树中第 6 大的数:3

关于二叉树相关题目的完整程序见:github

猜你喜欢

转载自blog.csdn.net/olizxq/article/details/84307738