bluecode-二叉树供暖问题

51 阅读3分钟

问题描述

天气越来越冷了,村子里有留守老人缺少照顾,会在这个冬天里挨冻,小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)
}