Skip to content

Commit c340745

Browse files
committed
feat: add solutions to lc problem: No.0968
No.0968.Binary Tree Cameras
1 parent d734bdd commit c340745

File tree

7 files changed

+278
-186
lines changed

7 files changed

+278
-186
lines changed

solution/0900-0999/0968.Binary Tree Cameras/README.md

+108-73
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,29 @@
4444

4545
<!-- 这里可写通用的实现逻辑 -->
4646

47-
贪心 + DFS。
47+
**方法一:动态规划(树形 DP)**
4848

49-
我们知道,
49+
对于每个节点,我们定义三种状态:
5050

51-
1. 如果在叶子节点放置摄像头,摄像头会覆盖当前叶子节点以及它的父节点;
52-
1. 如果在非叶子节点放置摄像头,摄像头会覆盖当前节点、它的子节点以及它的父节点。
51+
- `a`:当前节点有摄像头
52+
- `b`:当前节点无摄像头,但被子节点监控
53+
- `c`:当前节点无摄像头,也没被子节点监控
5354

54-
第二种方案始终优于第一种方案
55+
接下来,我们设计一个函数 $dfs(root)$,它将返回一个长度为 3 的数组,表示以 `root` 为根的子树中,三种状态下的最小摄像头数量。那么答案就是 $\min(dfs(root)[0], dfs(root)[1])$
5556

56-
因此,一种贪心的解法是,将摄像头放置在叶子节点的父节点上,然后移除所有被覆盖的节点,重复这一步骤,直至所有节点被移除。
57+
函数 $dfs(root)$ 的计算过程如下:
5758

58-
我们用数字 0, 1, 2 表示每个节点可能的三种状态,
59+
如果 `root` 为空,则返回 $[inf, 0, 0]$,其中 `inf` 表示一个很大的数,它用于表示不可能的情况。
5960

60-
- 0: 叶子节点
61-
- 1: 叶子节点的父节点,并且放置了摄像头
62-
- 2: 没放置摄像头,但是被摄像头覆盖
61+
否则,我们递归计算 `root` 的左右子树,分别得到 $[la, lb, lc]$ 和 $[ra, rb, rc]$。
6362

64-
定义 dfs(node) 返回每个节点的状态,对于每个节点,
63+
- 如果当前节点有摄像头,那么它的左右节点必须都是被监控的状态,即 $a = \min(la, lb, lc) + \min(ra, rb, rc) + 1$。
64+
- 如果当前节点无摄像头,但被子节点监控,那么子节点可以是其中之一或者两个都有摄像头,即 $b = \min(la + rb, lb + ra, la + ra)$。
65+
- 如果当前节点无摄像头,也没被子节点监控,那么子节点必须被其子节点监控,即 $c = lb + rb$。
6566

66-
1. 如果存在子节点,并且是叶子节点(`left == 0 || right == 0`),那么该节点需要放置摄像头,累加摄像头 ans,返回 1;
67-
1. 如果存在子节点,并且子节点放置了摄像头(`left == 1 || right == 1`),那么该节点可以直接被覆盖,返回 2;
68-
1. 否则把当前节点视为叶子节点,继续向上递归。
67+
最后,我们返回 $[a, b, c]$。
6968

70-
判断 `dfs(root)` 结果,若等于 0,说明还存在当前这一个叶子节点未被覆盖,摄像头数量 ans + 1 并返回,否则返回 ans
69+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是二叉树的节点数
7170

7271
<!-- tabs:start -->
7372

@@ -83,19 +82,19 @@
8382
# self.left = left
8483
# self.right = right
8584
class Solution:
86-
def minCameraCover(self, root: TreeNode) -> int:
85+
def minCameraCover(self, root: Optional[TreeNode]) -> int:
8786
def dfs(root):
88-
nonlocal ans
8987
if root is None:
90-
return 2
91-
left, right = dfs(root.left), dfs(root.right)
92-
if left == 0 or right == 0:
93-
ans += 1
94-
return 1
95-
return 2 if left == 1 or right == 1 else 0
96-
97-
ans = 0
98-
return (dfs(root) == 0) + ans
88+
return inf, 0, 0
89+
la, lb, lc = dfs(root.left)
90+
ra, rb, rc = dfs(root.right)
91+
a = min(la, lb, lc) + min(ra, rb, rc) + 1
92+
b = min(la + rb, lb + ra, la + ra)
93+
c = lb + rb
94+
return a, b, c
95+
96+
a, b, _ = dfs(root)
97+
return min(a, b)
9998
```
10099

101100
### **Java**
@@ -119,28 +118,21 @@ class Solution:
119118
* }
120119
*/
121120
class Solution {
122-
123-
private int ans;
124-
125121
public int minCameraCover(TreeNode root) {
126-
ans = 0;
127-
return (dfs(root) == 0) ? ans + 1 : ans;
122+
int[] ans = dfs(root);
123+
return Math.min(ans[0], ans[1]);
128124
}
129125

130-
private int dfs(TreeNode root) {
126+
private int[] dfs(TreeNode root) {
131127
if (root == null) {
132-
return 2;
133-
}
134-
int left = dfs(root.left);
135-
int right = dfs(root.right);
136-
if (left == 0 || right == 0) {
137-
++ans;
138-
return 1;
139-
}
140-
if (left == 1 || right == 1) {
141-
return 2;
128+
return new int[] {1 << 29, 0, 0};
142129
}
143-
return 0;
130+
var l = dfs(root.left);
131+
var r = dfs(root.right);
132+
int a = 1 + Math.min(Math.min(l[0], l[1]), l[2]) + Math.min(Math.min(r[0], r[1]), r[2]);
133+
int b = Math.min(Math.min(l[0] + r[1], l[1] + r[0]), l[0] + r[0]);
134+
int c = l[1] + r[1];
135+
return new int[] {a, b, c};
144136
}
145137
}
146138
```
@@ -159,26 +151,28 @@ class Solution {
159151
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
160152
* };
161153
*/
154+
struct Status {
155+
int a, b, c;
156+
};
157+
162158
class Solution {
163159
public:
164-
int ans;
165-
166160
int minCameraCover(TreeNode* root) {
167-
ans = 0;
168-
if (dfs(root) == 0) return ans + 1;
169-
return ans;
161+
auto [a, b, _] = dfs(root);
162+
return min(a, b);
170163
}
171164

172-
int dfs(TreeNode* root) {
173-
if (!root) return 2;
174-
int left = dfs(root->left), right = dfs(root->right);
175-
if (left == 0 || right == 0) {
176-
++ans;
177-
return 1;
165+
Status dfs(TreeNode* root) {
166+
if (!root) {
167+
return {1 << 29, 0, 0};
178168
}
179-
if (left == 1 || right == 1) return 2;
180-
return 0;
181-
}
169+
auto [la, lb, lc] = dfs(root->left);
170+
auto [ra, rb, rc] = dfs(root->right);
171+
int a = 1 + min({la, lb, lc}) + min({ra, rb, rc});
172+
int b = min({la + ra, la + rb, lb + ra});
173+
int c = lb + rb;
174+
return {a, b, c};
175+
};
182176
};
183177
```
184178

@@ -194,27 +188,68 @@ public:
194188
* }
195189
*/
196190
func minCameraCover(root *TreeNode) int {
197-
ans := 0
198-
var dfs func(root *TreeNode) int
199-
dfs = func(root *TreeNode) int {
191+
var dfs func(*TreeNode) (int, int, int)
192+
dfs = func(root *TreeNode) (int, int, int) {
200193
if root == nil {
201-
return 2
202-
}
203-
left, right := dfs(root.Left), dfs(root.Right)
204-
if left == 0 || right == 0 {
205-
ans++
206-
return 1
194+
return 1 << 29, 0, 0
207195
}
208-
if left == 1 || right == 1 {
209-
return 2
210-
}
211-
return 0
196+
la, lb, lc := dfs(root.Left)
197+
ra, rb, rc := dfs(root.Right)
198+
a := 1 + min(la, min(lb, lc)) + min(ra, min(rb, rc))
199+
b := min(la+ra, min(la+rb, lb+ra))
200+
c := lb + rb
201+
return a, b, c
212202
}
213-
if dfs(root) == 0 {
214-
return ans + 1
203+
a, b, _ := dfs(root)
204+
return min(a, b)
205+
}
206+
207+
func min(a, b int) int {
208+
if a < b {
209+
return a
215210
}
216-
return ans
211+
return b
212+
}
213+
```
214+
215+
### **TypeScript**
216+
217+
```ts
218+
/**
219+
* Definition for a binary tree node.
220+
* class TreeNode {
221+
* val: number
222+
* left: TreeNode | null
223+
* right: TreeNode | null
224+
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
225+
* this.val = (val===undefined ? 0 : val)
226+
* this.left = (left===undefined ? null : left)
227+
* this.right = (right===undefined ? null : right)
228+
* }
229+
* }
230+
*/
231+
232+
function minCameraCover(root: TreeNode | null): number {
233+
const dfs = (root: TreeNode | null): number[] => {
234+
if (!root) {
235+
return [1 << 29, 0, 0];
236+
}
237+
const [la, lb, lc] = dfs(root.left);
238+
const [ra, rb, rc] = dfs(root.right);
239+
const a = 1 + Math.min(la, lb, lc) + Math.min(ra, rb, rc);
240+
const b = Math.min(la + ra, la + rb, lb + ra);
241+
const c = lb + rb;
242+
return [a, b, c];
243+
};
244+
const [a, b, _] = dfs(root);
245+
return Math.min(a, b);
217246
}
218247
```
219248

249+
### **...**
250+
251+
```
252+
253+
```
254+
220255
<!-- tabs:end -->

0 commit comments

Comments
 (0)