华为笔试题街区监控

街区监控
题目描述
一个街区,为提高街区安全性,需在街区的路灯上安装若干摄像头,用一个二叉树表示街区的路灯,每个节点表示一个路灯,在路灯上安装摄像头。每个摄影头都可以监视其父对象、自身及其直接子对象。为保证每个路灯都被监控,请计算街区所需的最小摄像头数量。
输入描述:
输入一串字符,代表由前序排列的二叉树表示的路灯,字符由‘0’和‘#’组成,每个‘0’表示一个要监控路灯,‘#’表示子节点为空。
输出描述:
所需最小摄像头数量。
示例1输入输出示例仅供调试,后台判题数据一般不包含示例
输入

00##0#0

输出

2

说明
输入的路灯可以构建如下二叉树,1表示需要安装摄像头的路灯,输入的路灯数最少为2。

 0
 / \
1  1
      \
        0

leetcode 968. 监控二叉树 

首先是要根据先序序列重构二叉树,然后就和leetcode 968这题一模一样了。关键算法是要将每个节点的状态想清楚,分为3种状态,0:没有被覆盖 1:被覆盖但是没装摄像头 2:装了摄像头(自身、左右孩子、父节点都被覆盖)。所有节点初始时都时状态0,叶子节点不装摄像头。然后采用后序遍历的方式,从下到上,根据左右孩子节点的情况决定该节点是否要装摄像头。

#include 
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

struct Node
{
    Node* left;
    Node* right;
    Node():left(nullptr), right(nullptr){};
};

void preorder(Node*& root, string& str, int& index)
{
    if(index >= str.size()) return;
    if(str[index] == '0')
    {
        root = new Node();
        index++;
    }
    else
    {
        root = nullptr;
        index++;
        return;
    }
    preorder(root->left, str, index);
    preorder(root->right, str, index);
}

//每个节点有三种可能状态:
//0:该节点没有被覆盖
//1:该节点被覆盖,但是该节点没有摄像头
//2:该节点有摄像头(它自身、左右孩子和父节点都被覆盖)
int getState(Node* root, int& camaras)
{
    if(root == nullptr) return 1;
    int left = getState(root->left, camaras);
    int right = getState(root->right, camaras);
    //如果左右孩子存在没被覆盖的,该节点需要摄像头
    if(left == 0 || right == 0)
    {
        camaras++;
        return 2;
    }
    //如果左右孩子都被覆盖了,该节点返回没有被覆盖的状态
    if(left == 1 && right == 1) return 0;
    // 如果左右孩子存在装了摄像头的,那么该节点已经被覆盖了
    if(left + right > 2) return 1;
    return -1;
}

int main(void) {
    string str;
    while(true)
    {
        getline(cin, str);
        if(str.empty()) break;
        int index = 0;
        Node* root = nullptr;
        preorder(root, str, index);
        int camaras = 0;
        int rootState = getState(root, camaras);
        if(rootState == 0) camaras++;
        printf("%d\n", camaras);
    }
    return 0;
}

 

你可能感兴趣的:(华为笔试题街区监控)