[豆包MarsCode AI 刷题] 二叉树供暖问题题目解答

296 阅读5分钟

题目描述

天气越来越冷了,村子里有留守老人缺少照顾,会在这个冬天里挨冻,小R想运用自己的知识帮帮他们。已知村庄里每户人家作为一个节点,这些节点可以组成一个二叉树。我们可以在二叉树的节点上供应暖炉,每个暖炉可以为该节点的父节点、自身及其子节点带来温暖。给定一棵二叉树,求使整个村庄都暖和起来至少需要供应多少个暖炉?

本题按层遍历顺序描述二叉树的节点情况。值为 1,代表存在一个节点,值为 0,代表不存在该节点。

测试样例

样例1:

输入:nodes = [1, 1, 0, 1, 1]
输出:1

样例2:

输入:nodes = [1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1]
输出:3

样例3:

输入:nodes = [1, 1, 0, 1, 1, 1, 1]
输出:2

题目分析

我们可以在纸上绘制出这几个树的形状,然后可以分析得到:应当使用贪心算法 我们应当尽力在拥有孩子的根节点上面部署加热器,这样可以让更多的结点被覆盖。

因此就是每次查看根节点,分为两种情况:

  1. 若当前节点没有被覆盖,则直接在此节点放置加热器,然后将父亲节点和孩子节点都标记为覆盖。
  2. 若当前节点已经被覆盖,则查看其左右孩子,如果存在没有被覆盖的,则在当前节点放置加热器,并将父节点和左右孩子标记为覆盖。

算法实现

根据层次遍历建树

首先题目给出的是一个层序遍历结果,层序遍历其实与图中的bfs遍历一致,用一个队列来维护,将当前节点(最初是)树根节点,然后将数组下表index设置为1,先考虑左孩子,如果vertices[i]空,则表示没有左孩子,否则就建立一个结点,然后将当前节点的左孩子设置为这个新建的结点,并将左孩子入队,右孩子处理同理。

先序遍历

用非递归实现一个先序遍历主要是维护一个栈,从树根节点开始,如果右左孩子,就将自己入栈并转入到左孩子,直到左孩子为空,则表示已经到达了叶子结点,由于我们只考虑跟节点,因此弹栈,这时候拿到的就是根节点,然后按照刚才的两种情况进行讨论,然后访问右孩子并继续这个过程,直到栈空为止。

解题代码

class TreeNode:
    def __init__(self, value=0):
        self.value = value  # 1 表示存在,0 表示不存在
        self.left = None
        self.right = None
        self.parent = None  # 添加父节点属性
        self.isSetHeat = None  # 是否放置暖炉

def build_tree(nodes):
    if not nodes or nodes[0] == 0:
        return None
    
    queue = []
    root = TreeNode(0)  # 初始值设置为0,表示存在一个节点
    queue.append(root)
    
    index = 1
    while queue and index < len(nodes):
        current = queue.pop(0)

        # 左子节点
        if index < len(nodes) and nodes[index] != 0:
            current.left = TreeNode(0)
            current.left.parent = current  # 设置父节点
            queue.append(current.left)
        index += 1
        
        # 右子节点
        if index < len(nodes) and nodes[index] != 0:
            current.right = TreeNode(0)
            current.right.parent = current  # 设置父节点
            queue.append(current.right)
        index += 1
    
    return root

def solution(nodes):
    root = build_tree(nodes)
    heaters = 0

    def place_heaters():
        nonlocal heaters
        stack = []
        node = root
        
        while node or stack:
            while node:
                # 只将非叶子节点入栈
                if node.left or node.right:
                    stack.append(node)
                node = node.left
            
            if stack:  # 确保栈不为空
                node = stack.pop()
                
                # 检查当前节点是否需要放置暖炉
                if node.isSetHeat is None:
                    node.isSetHeat = True  # 放置暖炉
                    heaters += 1
                    # 设置父节点和子节点的 isSetHeat
                    if node.parent:
                        node.parent.isSetHeat = True
                    if node.left:
                        node.left.isSetHeat = True
                    if node.right:
                        node.right.isSetHeat = True
            
                # 处理右子树
                node = node.right
            else:
                node = None  # 确保继续外层循环

    place_heaters()
    
    return heaters

if __name__ == "__main__":
    # 测试用例
    print(solution([1, 1, 0, 1, 1]) == 1)  # 预期输出 True
    print(solution([1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1]) == 3)  # 预期输出 True
    print(solution([1, 1, 0, 1, 1, 1, 1]) == 2)  # 预期输出 True

豆包marcode

在解决这类问题时,豆包 MarsCode AI 提供了一系列强大的功能和显著的优势,可以全面提升编程效率和算法理解能力:

  1. 代码生成:
    AI 能够根据用户提供的问题描述,快速生成完整且高效的代码框架,从而大幅缩短开发时间。这种能力不仅适用于简单问题,还能扩展到复杂场景,例如动态规划、树形 DP 等。无论是初学者还是资深开发者,都可以从中受益,直接专注于问题的逻辑设计和实现细节。
  2. 算法优化:
    MarsCode AI 不仅可以生成代码,还能够分析现有代码并提供优化建议。例如,它能够针对算法中的低效部分提出改进方案,从而降低时间复杂度或空间复杂度。特别是在解决动态规划等复杂问题时,AI 可以通过细致的分析发现隐藏的优化机会,让代码运行得更快、更稳定。
  3. 错误检测:
    在编写代码时,难免会遇到逻辑错误或边界条件处理不当的情况。MarsCode AI 能够自动检测代码中的潜在问题,包括语法错误、逻辑错误甚至性能瓶颈,并及时给出修改建议。这种功能不仅提高了调试效率,也显著减少了运行时错误的可能性。