- 监控二叉树 (LeetCode 968)
这段代码实现了一个算法,用于在二叉树中放置最少数量的摄像头以监控所有节点。该算法使用了后序遍历(DFS)来确定每个节点的状态,并计算所需的最小摄像头数量。
核心思想:
定义了三种状态值:
0:节点未被覆盖。
1:节点上有摄像头。
2:节点被覆盖(由其他摄像头覆盖)。
使用后序遍历(先递归遍历左右子节点,再处理当前节点)来确定每个节点的状态。
如果一个节点的任一子节点状态为 0(未被覆盖),则该节点必须放置摄像头(状态为 1)。
如果一个节点的两个子节点状态都为 2(都被覆盖),则该节点可以不放置摄像头(状态为 0)。
如果一个节点的任一子节点状态为 1(有摄像头),则该节点可以被覆盖(状态为 2)。
代码结构:
minCameraCover(TreeNode root):主函数,调用 dfsMin 函数并处理根节点的情况。
dfsMin(TreeNode root):递归函数,计算每个节点的状态并更新摄像头数量。
点击查看代码
//968. 监控二叉树
private int res=0;
public int minCameraCover(TreeNode root) {
if (dfsMin(root)==0){//确保根节点有被覆盖
res++;
}
return res;
}
/**
* 节点的状态值:
* 0 表示无覆盖
* 1 表示 有摄像头
* 2 表示有覆盖
* 后序遍历,根据左右节点的情况,来判读 自己的状态
*/
private int dfsMin(TreeNode root) {
if (root == null) {
// 空节点默认为有覆盖状态,避免在叶子节点上放摄像头
return 2;
}
//采用后序遍历的方式,先确定孩子的状态
int left = dfsMin(root.left);
int right = dfsMin(root.right);
if (left == 0 || right == 0) {//只要有一个孩子为未覆盖状态,该结点就必须放置监控
res++;//优先级高于充当被覆盖状态,因此这个if判断在前面
return 1;
}else if (left==2&&right==2){//只有当两个孩子都是被覆盖状态该结点才会是未覆盖状态
return 0;
} else if (left==1||right==1) {//有一个孩子是监控,它就可以是被覆盖状态,优先级低于充当监控
return 2;
}
return -1;//不可能被执行的代码
}
- 单调递增的数字 (LeetCode 738)
这段代码实现了一个算法,用于找到一个给定整数 n 的最大单调递增子序列。该算法通过贪心策略和字符串操作来实现。
核心思想:
将整数 n 转换为字符数组,以便逐位操作。
从左到右扫描字符数组,找到第一个不满足单调递增条件的位置 i。
将位置 i 的数字减 1,并将其后面的所有数字置为 9,以确保从位置 i 开始的子序列是单调递减的。
将修改后的字符数组转换回整数,得到最大单调递增子序列。
代码结构:
monotoneIncreasingDigits(int n):主函数,实现上述算法。
check(int n):辅助函数,用于检查一个整数是否单调递增(虽然在最终代码中未使用)。
点击查看代码
//738. 单调递增的数字
public int monotoneIncreasingDigits(int n) {
// 将数字转换为字符数组
char[] chars = String.valueOf(n).toCharArray();
int i = 0;
// 找到开始递减的位置
while (i < chars.length-1 && chars[i] <= chars[i+1]) {
i++;
}
if (i < chars.length-1) {//存在递减数字
// 要确保开始递减位置的数字减1后不影响前面的递增顺序,所以减1位置的前面不能有相同数字
while (i >0 && chars[i] == chars[i-1]) {
i--;
}
chars[i]--;
// 减1位置之后的数字都置为 9
for (i = i + 1; i < chars.length; i++) {
chars[i] = '9';
}
}
// 将字符数组转换为整数
return Integer.parseInt(new String(chars));
}