问题描述
天气越来越冷了,村子里有留守老人缺少照顾,会在这个冬天里挨冻,小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
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
TreeNode *buildTree(const vector<int> &nodes) {
if (nodes.empty() || nodes[0] == 0) {
return nullptr;
}
TreeNode *root = new TreeNode(nodes[0]);
queue<TreeNode *> q;
q.push(root);
int i = 1;
while (!q.empty() && i < nodes.size()) {
TreeNode *node = q.front();
q.pop();
if (node == nullptr) {
continue;
}
// 左子节点
if (i < nodes.size()) {
if (nodes[i] != 0) {
node->left = new TreeNode(nodes[i]);
q.push(node->left);
} else {
q.push(nullptr);
}
i++;
}
// 右子节点
if (i < nodes.size()) {
if (nodes[i] != 0) {
node->right = new TreeNode(nodes[i]);
q.push(node->right);
} else {
q.push(nullptr);
}
i++;
}
}
return root;
}
int minHeaters(TreeNode *root) {
int result = 0;
// 后序遍历计算节点状态
function<int(TreeNode *)> postorder = [&](TreeNode *node) -> int {
if (node == nullptr) {
return 1; // 空节点默认为已覆盖
}
int left = postorder(node->left);
int right = postorder(node->right);
// 状态转移规则
if (left == 0 || right == 0) {
// 子节点未被覆盖,必须在当前节点放置暖炉
result++;
return 2; // 当前节点放置暖炉
}
if (left == 2 || right == 2) {
// 子节点放置了暖炉,当前节点被覆盖
return 1;
}
// 否则,当前节点未被覆盖
return 0;
};
// 特殊情况:空树
if (root == nullptr) {
return 0;
}
// 计算根节点状态
if (postorder(root) == 0) {
result++; // 如果根节点未被覆盖,需要额外放置一个暖炉
}
return result;
}
int solution(vector<int> nodes) {
TreeNode *root = buildTree(nodes);
int heaters = minHeaters(root);
// 释放树节点内存
function<void(TreeNode *)> releaseTree = [&](TreeNode *node) {
if (node == nullptr)
return;
releaseTree(node->left);
releaseTree(node->right);
delete node;
};
releaseTree(root);
return heaters;
}
int main() {
vector<int> nodes1 = {1, 1, 0, 1, 1};
vector<int> nodes2 = {1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1};
vector<int> nodes3 = {1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1};
cout << (solution(nodes1) == 1) << endl; // 输出:1
cout << (solution(nodes2) == 3) << endl; // 输出:1
cout << (solution(nodes3) == 3) << endl; // 输出:1
return 0;
}
package main
import "fmt"
type TreeNode struct {
val int
left *TreeNode
right *TreeNode
}
func buildTree(nodes []int) *TreeNode {
if len(nodes) == 0 || nodes[0] == 0 {
return nil
}
root := &TreeNode{val: nodes[0]}
queue := []*TreeNode{root}
i := 1
for len(queue) > 0 && i < len(nodes) {
node := queue[0]
queue = queue[1:]
if i < len(nodes) {
if nodes[i] != 0 {
node.left = &TreeNode{val: nodes[i]}
queue = append(queue, node.left)
}
i++
}
if i < len(nodes) {
if nodes[i] != 0 {
node.right = &TreeNode{val: nodes[i]}
queue = append(queue, node.right)
}
i++
}
}
return root
}
func minHeaters(root *TreeNode) int {
result := 0
var postorder func(*TreeNode) int
postorder = func(node *TreeNode) int {
if node == nil {
return 1
}
left := postorder(node.left)
right := postorder(node.right)
if left == 0 || right == 0 {
result++
return 2
}
if left == 2 || right == 2 {
return 1
}
return 0
}
if root == nil {
return 0
}
if postorder(root) == 0 {
result++
}
return result
}
func solution(nodes []int) int {
root := buildTree(nodes)
return minHeaters(root)
}
func main() {
// You can add more test cases here
fmt.Println(solution([]int{1, 1, 0, 1, 1}) == 1)
fmt.Println(solution([]int{1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1}) == 3)
fmt.Println(solution([]int{1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1}) == 3)
}