一个街区为了提高街区安全性,需要在街区的路灯上安装若干摄像头,用一个二叉树表示街区的路灯。 每个节点表示一个路灯,在路灯上安装摄像头。每个摄像头可以监控其自身、父对象和直接子对象。 为保证每个路灯都被监控,请计算所需的最小摄像头数。
输入描述:
输入一串字符,代表由前序排列的二叉树表示的路灯,字符由'0'和'#'组成,每个'0'表示一个要监控的路灯, '#'表示子节点为空
输出描述:
所需最小摄像头数。
思路
构建二叉树采用消融的方式:将'0##'变成一个‘#’放回字符串。重复这个方式直到 字符串只剩下一个‘#’,树就建成了。
建树的过程实际上是一个递归返回的过程,和我们递归遍历一棵树是等价的。 因此,可以把求解的过程和建树一同进行。每找到一棵树[既0##]:
1. 确定子树放的路灯数量;
2.确定子树需不需要父节点帮忙放路灯
3.确定子树的根有没有放路灯,从而决定自己需不需要放。
struct TreeNode { char val; char tag; bool need; bool put; size_t count; TreeNode *left, *right; TreeNode(char x) : val(x), tag(x), left(NULL), right(NULL), need(false), put(false), count(0){} }; void delTree(TreeNode* root){ queue<TreeNode*> fifo; fifo.push(root); while(!fifo.empty()){ TreeNode* node = fifo.front(); if(node){ fifo.push(node->left); fifo.push(node->right); delete node; } fifo.pop(); } } size_t makeTree(string s){ stack<TreeNode*> st; for(int i = 0; i < s.size();++i){ if(!st.empty() && (s[i] == '#' && st.top()->tag == '#')){ TreeNode* r = new TreeNode('#'); while(!st.empty() && st.top()->tag == '#'){ TreeNode* l = st.top(); st.pop(); TreeNode* root = st.top(); st.pop(); root->left = l; root->right = r; root->tag = '#'; root->count += l->count; root->count += r->count; if(l->need || r->need){ root->count += 1; root->put = true; root->need = false; }else if(l->put || r->put){ root->need = false; root->put = false; }else{ root->put = false; root->need = true; } r = root; } st.push(r); }else{ st.push(new TreeNode(s[i])); } } auto root = st.top(); size_t result = root->need ? root->count + 1 : root->count; delTree(root); return result; }