代码随想录Day37 | Leetcode 738、968
一、738 单调递增的数字
题目链接:738 单调递增的数字
核心:要求数字从高到低数位递增(相邻元素相同也视为递增),如果遇到不是递增的情况,要明确如何修改才能使其满足各数位递增:高数位数字减1,低数位置为9。
此外,还需注意得从后往前遍历进行各数位元素的修改,否则如果从前往后遍历,比如443,从高数位开始遍历,第一个数位与第二个数位符合递增,无需修改,第二个数位与第三个数位不满足递增,则修改成:439,此时修改后的数字依然不满足递增,因此从前往后遍历是会出现bug。
int monotoneIncreasingDigits(int n) {
//从后往前遍历
string str=to_string(n);
int flag=str.size(); //标识从何处开始赋值为9
for(int i=str.size()-1;i>0;i--)
{
if(str[i-1]>str[i])
{//前一个元素更大时需将前一个元素-1,且令当前元素为9
str[i-1]--;
flag=i; //标识此处开始到最后一个元素需要赋值为9
}
}
for(int i=flag;i<str.size();++i)
str[i]='9';
return stoi(str);
}
二、968 监控二叉树
题目链接:968 监控二叉树
核心:首先对于二叉树问题,明确遍历顺序,由于要求放置最少的摄像机,因此考虑从叶子节点开始遍历(2^(n-1)),最终递归到根节点(1),可知后序遍历符合此要求:左右中。
然后明确节点的三种状态:0—无覆盖,1–有摄像机,2–有覆盖,无覆盖表示该节点没有摄像机且不处于有摄像机节点的孩子节点或父节点(未被摄像机范围覆盖),有覆盖表示该节点没有摄像机但处于有摄像机节点的孩子节点或父节点。以及空节点被看成有覆盖(比如叶子节点)。
其次,明确节点在不同状态下的情况应如何处理:
第一,左孩子和右孩子有覆盖(2),则父节点无覆盖(0);(为何此处不放置摄像机?)
第二,左孩子或右孩子无覆盖(0),则父节点需要放置摄像机(1);
第三,左孩子或右孩子有摄像机(1),则父节点有覆盖(2)。
最后,需要判断根节点是否有覆盖,若无覆盖(0)则根节点需放置摄像机。(在主函数实现)
//3种状态:0--无覆盖;1--有摄像机;2--有覆盖
int res; //摄像机的数量
int traversal(TreeNode* cur)
{//后序遍历:左右中,从叶子节点开始,递归到根节点
if(cur==nullptr)
return 2; //空节点表示有覆盖
int left=traversal(cur->left); //左
int right=traversal(cur->right); //右
if(left==2 && right==2)
return 0; //左右孩子都有覆盖,则中间节点(父节点)无覆盖
if(left==0 || right==0)
{//左孩子或者右孩子无覆盖,则父节点(中间)需要摄像机
res++;
return 1;
}
if(left==1 || right==1)
return 2; //左孩子或者右孩子有摄像机,则父节点有覆盖
return -1; //无状态
}
int minCameraCover(TreeNode* root) {
res=0;
if(traversal(root)==0)
res++; //最终返回的中间节点(根节点)无覆盖,则根节点还需要摄像机
return res;
}