题目描述
天气越来越冷了,村子里有留守老人缺少照顾,会在这个冬天里挨冻,小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
题目分析
我们可以在纸上绘制出这几个树的形状,然后可以分析得到:应当使用贪心算法
我们应当尽力在拥有孩子的根节点上面部署加热器,这样可以让更多的结点被覆盖。
因此就是每次查看根节点,分为两种情况:
- 若当前节点没有被覆盖,则直接在此节点放置加热器,然后将父亲节点和孩子节点都标记为覆盖。
- 若当前节点已经被覆盖,则查看其左右孩子,如果存在没有被覆盖的,则在当前节点放置加热器,并将父节点和左右孩子标记为覆盖。
算法实现
根据层次遍历建树
首先题目给出的是一个层序遍历结果,层序遍历其实与图中的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 提供了一系列强大的功能和显著的优势,可以全面提升编程效率和算法理解能力:
- 代码生成:
AI 能够根据用户提供的问题描述,快速生成完整且高效的代码框架,从而大幅缩短开发时间。这种能力不仅适用于简单问题,还能扩展到复杂场景,例如动态规划、树形 DP 等。无论是初学者还是资深开发者,都可以从中受益,直接专注于问题的逻辑设计和实现细节。 - 算法优化:
MarsCode AI 不仅可以生成代码,还能够分析现有代码并提供优化建议。例如,它能够针对算法中的低效部分提出改进方案,从而降低时间复杂度或空间复杂度。特别是在解决动态规划等复杂问题时,AI 可以通过细致的分析发现隐藏的优化机会,让代码运行得更快、更稳定。 - 错误检测:
在编写代码时,难免会遇到逻辑错误或边界条件处理不当的情况。MarsCode AI 能够自动检测代码中的潜在问题,包括语法错误、逻辑错误甚至性能瓶颈,并及时给出修改建议。这种功能不仅提高了调试效率,也显著减少了运行时错误的可能性。