Given a binary tree, we install cameras on the nodes of the tree.
Each camera at a node can monitor its parent, itself, and its immediate children.
Calculate the minimum number of cameras needed to monitor all nodes of the tree.
Example 1:
Input: [0,0,null,0,0]
Output: 1
Explanation: One camera is enough to monitor all nodes if placed as shown.
Example 2:
Input: [0,0,null,0,null,0,null,null,0]
Output: 2
Explanation: At least two cameras are needed to monitor all nodes of the tree. The above image shows one of the valid configurations of camera placement.
Note:
- The number of nodes in the given tree will be in the range
[1, 1000]
. - Every node has value 0.
這道題給了一棵二叉樹,說是可以在結點上放相機,可以拍父結點,自身,和左右子結點,現在問我們最少需要多少個相機才能拍到所有的結點。由於是一道 Hard 題目,博主下意識的看了一下 Related Topics,發現是 DP。於是博主就開始思考如何定義 dp,並且思考狀態轉移方程。但是沒有想出可行的解法,於是去論壇上逛了一下,發現大家用的都是貪婪算法 Greedy Algorithm,看來博主被 Topics 誤導了。不過不要緊,重要的是跟着大神 lee215 一起來解題吧。這里先來考慮,到底把相機放在什么位置可以拍到最多的結點?是葉結點嗎?不一定是,因為若放在葉結點,只能拍到該葉結點和其父結點兩個而已。是根結點嗎?也不一定,因為放在根結點,最多拍到根結點和其左右兩個子結點,總共三個而已。最優解是放在葉結點的父結點上,這樣最多可以拍到四個結點。所以策略應該是先找到葉結點,讓后在其父結點放上相機,同時標記父結點的父結點為被拍到了。這樣就有3種不同的狀態,用0來表示當前結點是葉結點,1表示當前結點是葉結點的父結點,並被放置了相機,2表示當前結點的是葉結點的爺爺結點,並被相機拍到了。這里使用一個子函數,將全局變量 res 傳進去,用來記錄放置的相機的總個數。在遞歸函數中,若當前結點不存在,則返回2,空結點也可看作已經被相機拍到了。否則分別對左右子結點調用遞歸函數,若二者中有一個返回0了,當前結點至少有一個子結點是葉結點,需要在當前位置放一個相機,結果 res 自增1,並返回1。否則若左右子結點的返回值有一個為1,說明左右子結點中至少有一個已經被放上了相機,當前結點已經被拍到了,返回2。若都不是,則說明當前結點是葉結點,返回0。在主函數中,若對根結點調用遞歸的返回值是0,說明根結點是葉結點,此時沒有辦法,只能在葉結點上放個相機了,所以要加上1,否則不用加,參見代碼如下:
class Solution {
public:
int minCameraCover(TreeNode* root) {
int res = 0;
return (helper(root, res) < 1 ? 1 : 0) + res;
}
// Return 0 if leaf, 1 if parent of leaf with camera on this node, 2 if covered without camera on this node.
int helper(TreeNode* node, int& res) {
if (!node) return 2;
int left = helper(node->left, res), right = helper(node->right, res);
if (left == 0 || right == 0) {
++res;
return 1;
}
return (left == 1 || right == 1) ? 2 : 0;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/968
類似題目:
Distribute Coins in Binary Tree
參考資料:
https://leetcode.com/problems/binary-tree-cameras/
https://leetcode.com/problems/binary-tree-cameras/discuss/211180/JavaC%2B%2BPython-Greedy-DFS