968. 监控二叉树(递归+贪心)
給定一個二叉樹,我們在樹的節點上安裝攝像頭。
節點上的每個攝影頭都可以監視其父對象、自身及其直接子對象。
計算監控樹的所有節點所需的最小攝像頭數量。
示例 1:
輸入:[0,0,null,0,0]
輸出:1
解釋:如圖所示,一臺攝像頭足以監控所有節點。
示例 2:
輸入:[0,0,null,0,null,0,null,null,0]
輸出:2
解釋:需要至少兩個攝像頭來監視樹的所有節點。 上圖顯示了攝像頭放置的有效位置之一。
提示:
給定樹的節點數的范圍是 [1, 1000]。
每個節點的值都是 0。
————————————————————————————————————————————————————————
題目要求最小攝像頭數目,如果從頭節點開始看,就只能省一個攝像頭,而如果從葉子節點開始看,就可以省下指數級的攝像頭數目;
所以可以確定遍歷順序是從葉子節點開始向上遍歷,讓葉子節點的父節點裝攝像頭即可;
很容易想到是后序遍歷,根據貪心思想有:
局部最優:葉子節點的父節點安攝像頭,所用攝像頭最少;
全局最優:整體二叉樹所用攝像頭最少;
然后該考慮裝攝像頭的情況了,這里需要考慮每個節點可能的狀態,有三種:
1,有攝像頭覆蓋
2,沒有攝像頭覆蓋
3,有攝像頭
注意:這里“沒有攝像頭”狀態就是1和2了;
所以可以用三個數字表示節點狀態:
0:該節點無覆蓋
1:該節點有攝像頭
2:該節點有覆蓋
這里還需要考慮一點:空節點怎么辦?(終止條件)
空節點如果是沒有覆蓋狀態,那么葉節點就得有攝像頭,所以我們需要將空節點賦為有覆蓋的狀態;
整個遞歸函數整體框架有了,接下來是每一層的邏輯情況,有四種:
1,左孩子和右孩子都有覆蓋(2),那么父節點就需要是無覆蓋狀態(0)
2,左孩子和右孩子至少有一個沒有覆蓋,那么父節點就需要是有攝像頭狀態(1)
3,左孩子和右孩子至少有一個有攝像頭,那么父節點就需要是有覆蓋的狀態(2)
4,頭節點沒有覆蓋,那么需要單獨給它加一個攝像頭;
分析完了,代碼如下:
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/ class Solution { public:int ans = 0;//0:無覆蓋 1:有攝像頭 2:有覆蓋int traverse(TreeNode* root) {if (!root) return 2;int left = traverse(root -> left);int right = traverse(root -> right);//情況二if (!left || !right) {ans++;return 1;}//情況三if (left == 1 || right == 1) {return 2;}//情況一if (left == 2 && right == 2) {return 0;}return -1;}int minCameraCover(TreeNode* root) {//情況四if (!traverse(root)) {ans++;}return ans;} };總結
以上是生活随笔為你收集整理的968. 监控二叉树(递归+贪心)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 738. 单调递增的数字(贪心算法)
- 下一篇: 77. 组合(回溯算法)