代码随想录-刷题第三十七天
738. 单调递增的数字
思路:从后向前遍历,如果前一位大于当前位,就让前一位减一,记录当前位的下标,遍历结束后,从记录的下标开始往后都要变成9。
**局部最优:**遇到strNum[i - 1]
> strNum[i]
的情况,让strNum[i - 1]--
,然后strNum[i]
给为9,可以保证这两位变成最大单调递增整数。
**全局最优:**得到小于等于N的最大单调递增的整数。
这里使用字符数组来进行操作
class Solution {
public int monotoneIncreasingDigits(int n) {
String s = String.valueOf(n);
char[] chars = s.toCharArray();
// 用来标记赋值9从哪里开始
// 设置为这个默认值,为了防止第二个for循环在start没有被赋值的情况下执行
int start = s.length();
for (int i = s.length() - 2; i >= 0; i--) {
if (chars[i] > chars[i + 1]) {
chars[i]--;
start = i + 1;
}
}
for (int i = start; i < s.length(); i++) {
chars[i] = '9';
}
return Integer.parseInt(String.valueOf(chars));
}
}
968. 监控二叉树
思路:可以找到规律,叶子节点是一定不能存放摄像头的,因为一个摄像头可以监测三层的节点,如果放在叶子节点上就少了一层,由此可以确定遍历顺序位自底向上的后序遍历。可以设0为当前节点无覆盖,1为当前节点有摄像头,2为当前节点有覆盖。
**局部最优:**让叶子节点的父节点安摄像头,所用摄像头最少;
**全局最优:**全部摄像头数量所用最少!
空节点不能是无覆盖的状态,这样叶子节点就要放摄像头了,空节点也不能是有摄像头的状态,这样叶子节点的父节点就没有必要放摄像头了,而是可以把摄像头放在叶子节点的爷爷节点上。
所以空节点的状态只能是有覆盖,这样就可以在叶子节点的父节点放摄像头了
class Solution {
int res = 0;
public int minCameraCover(TreeNode root) {
// 情况4 对根节点的状态做检验,防止根节点是无覆盖状态
if(traversal(root) == 0) {
res++;
}
return res;
}
/**
节点的状态值:
0 表示 无覆盖
1 表示 有摄像头
2 表示 有覆盖
后序遍历,根据左右节点的情况,来判读当前节点的状态
*/
private int traversal(TreeNode cur) {
if(cur == null){
// 空节点默认为 有覆盖状态,避免在叶子节点上放摄像头
return 2;
}
int left = traversal(cur.left);
int right = traversal(cur.right);
// 情况1
// 如果左右节点都覆盖了的话,那么本节点的状态就应该是无覆盖,没有摄像头
if (left == 2 && right == 2) return 0;
// 情况2
// left == 0 && right == 0 左右节点无覆盖
// left == 1 && right == 0 左节点有摄像头,右节点无覆盖
// left == 0 && right == 1 左节点有无覆盖,右节点摄像头
// left == 0 && right == 2 左节点无覆盖,右节点覆盖
// left == 2 && right == 0 左节点覆盖,右节点无覆盖
if (left == 0 || right == 0) {
// 状态值为 1 摄像头数 +1
res++;
return 1;
}
// 情况3
// left == 1 && right == 2 左节点有摄像头,右节点有覆盖
// left == 2 && right == 1 左节点有覆盖,右节点有摄像头
// left == 1 && right == 1 左右节点都有摄像头
// 其他情况前段代码均已包含
// 那么本节点就是处于被覆盖状态
if (left == 1 || right == 1) return 2;
// 以上代码没有使用 else,主要是为了把各个分支条件展现出来
// 这个 return -1 逻辑不会走到这里。
return -1;
}
}
在以上代码的基础上,再进行精简,代码如下:
其实就是在之前版本的基础上,使用else把一些情况直接覆盖掉。
class Solution {
int res = 0;
public int minCameraCover(TreeNode root) {
// 对根节点的状态做检验,防止根节点是无覆盖状态
if (traverse(root) == 0) res++;
return res;
}
private int traverse(TreeNode cur) {
if (cur == null) return 2;
int left = traverse(cur.left);
int right = traverse(cur.right);
// 如果左右节点都覆盖了的话,那么本节点的状态就应该是无覆盖,没有摄像头
if (left == 2 && right == 2) return 0;
else if (left == 0 || right == 0) {
// 状态值为 1 摄像头数 +1;
res++;
return 1;
} else return 2;
}
}