|
|
|
|
package class07;
|
|
|
|
|
|
|
|
|
|
// 本题测试链接 : https://leetcode.com/problems/binary-tree-cameras/
|
|
|
|
|
public class Code02_MinCameraCover {
|
|
|
|
|
|
|
|
|
|
public static class TreeNode {
|
|
|
|
|
public int value;
|
|
|
|
|
public TreeNode left;
|
|
|
|
|
public TreeNode right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int minCameraCover1(TreeNode root) {
|
|
|
|
|
Info data = process1(root);
|
|
|
|
|
return (int) Math.min(data.uncovered + 1, Math.min(data.coveredNoCamera, data.coveredHasCamera));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 潜台词:x是头节点,x下方的点都被覆盖的情况下
|
|
|
|
|
public static class Info {
|
|
|
|
|
public long uncovered; // x没有被覆盖,x为头的树至少需要几个相机
|
|
|
|
|
public long coveredNoCamera; // x被相机覆盖,但是x没相机,x为头的树至少需要几个相机
|
|
|
|
|
public long coveredHasCamera; // x被相机覆盖了,并且x上放了相机,x为头的树至少需要几个相机
|
|
|
|
|
|
|
|
|
|
public Info(long un, long no, long has) {
|
|
|
|
|
uncovered = un;
|
|
|
|
|
coveredNoCamera = no;
|
|
|
|
|
coveredHasCamera = has;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 所有可能性都穷尽了
|
|
|
|
|
public static Info process1(TreeNode X) {
|
|
|
|
|
if (X == null) { // base case
|
|
|
|
|
return new Info(Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Info left = process1(X.left);
|
|
|
|
|
Info right = process1(X.right);
|
|
|
|
|
// x uncovered x自己不被覆盖,x下方所有节点,都被覆盖
|
|
|
|
|
// 左孩子: 左孩子没被覆盖,左孩子以下的点都被覆盖
|
|
|
|
|
// 左孩子被覆盖但没相机,左孩子以下的点都被覆盖
|
|
|
|
|
// 左孩子被覆盖也有相机,左孩子以下的点都被覆盖
|
|
|
|
|
long uncovered = left.coveredNoCamera + right.coveredNoCamera;
|
|
|
|
|
|
|
|
|
|
// x下方的点都被covered,x也被cover,但x上没相机
|
|
|
|
|
long coveredNoCamera = Math.min(
|
|
|
|
|
// 1)
|
|
|
|
|
left.coveredHasCamera + right.coveredHasCamera,
|
|
|
|
|
|
|
|
|
|
Math.min(
|
|
|
|
|
// 2)
|
|
|
|
|
left.coveredHasCamera + right.coveredNoCamera,
|
|
|
|
|
|
|
|
|
|
// 3)
|
|
|
|
|
left.coveredNoCamera + right.coveredHasCamera));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// x下方的点都被covered,x也被cover,且x上有相机
|
|
|
|
|
long coveredHasCamera =
|
|
|
|
|
Math.min(left.uncovered, Math.min(left.coveredNoCamera, left.coveredHasCamera))
|
|
|
|
|
|
|
|
|
|
+ Math.min(right.uncovered, Math.min(right.coveredNoCamera, right.coveredHasCamera))
|
|
|
|
|
|
|
|
|
|
+ 1;
|
|
|
|
|
|
|
|
|
|
return new Info(uncovered, coveredNoCamera, coveredHasCamera);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static int minCameraCover2(TreeNode root) {
|
|
|
|
|
Data data = process2(root);
|
|
|
|
|
return data.cameras + (data.status == Status.UNCOVERED ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 以x为头,x下方的节点都是被covered,x自己的状况,分三种
|
|
|
|
|
public static enum Status {
|
|
|
|
|
UNCOVERED, COVERED_NO_CAMERA, COVERED_HAS_CAMERA
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 以x为头,x下方的节点都是被covered,得到的最优解中:
|
|
|
|
|
// x是什么状态,在这种状态下,需要至少几个相机
|
|
|
|
|
public static class Data {
|
|
|
|
|
public Status status;
|
|
|
|
|
public int cameras;
|
|
|
|
|
|
|
|
|
|
public Data(Status status, int cameras) {
|
|
|
|
|
this.status = status;
|
|
|
|
|
this.cameras = cameras;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Data process2(TreeNode X) {
|
|
|
|
|
if (X == null) {
|
|
|
|
|
return new Data(Status.COVERED_NO_CAMERA, 0);
|
|
|
|
|
}
|
|
|
|
|
Data left = process2(X.left);
|
|
|
|
|
Data right = process2(X.right);
|
|
|
|
|
int cameras = left.cameras + right.cameras;
|
|
|
|
|
|
|
|
|
|
// 左、或右,哪怕有一个没覆盖
|
|
|
|
|
if (left.status == Status.UNCOVERED || right.status == Status.UNCOVERED) {
|
|
|
|
|
return new Data(Status.COVERED_HAS_CAMERA, cameras + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 左右孩子,不存在没被覆盖的情况
|
|
|
|
|
if (left.status == Status.COVERED_HAS_CAMERA || right.status == Status.COVERED_HAS_CAMERA) {
|
|
|
|
|
return new Data(Status.COVERED_NO_CAMERA, cameras);
|
|
|
|
|
}
|
|
|
|
|
// 左右孩子,不存在没被覆盖的情况,也都没有相机
|
|
|
|
|
return new Data(Status.UNCOVERED, cameras);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|