代码随想录Day37 | 738.单调递增的数字 968.监控二叉树
738.单调递增的数字
文档讲解:代码随想录
视频讲解: 贪心算法,思路不难想,但代码不好写!LeetCode:738.单调自增的数字
状态
本题可以通过比较低位与高位,如果低位比高位小,则变为9,同时比较高位的高位,如果高位比高位的高位大,那么就–。遍历完一次后,再从高位向低位遍历,如果高位比低位大,那么修改低位的值为高位的值
//统计每个位的字符
//然后按个位 十位这样组成一个数组
//如果i<i+1那么将nums[i]变为9
//接着比较i+1>=i+2 或者 i+1是否是最后一个 nums[i+1] -1
//最后在从右向左遍历,如果后遍历比前遍历的小则修改
class Solution {
public:
int monotoneIncreasingDigits(int n) {
if(n ==0) return 0;
vector<int> check;
while(n)
{
int temp = n%10;
check.push_back(temp);
n = n/10;
}
for(int i = 0;i<check.size()-1;i++)
{
if(check[i]<check[i+1])
{
check[i]=9;
if(i+1 == check.size()-1 || (i+2<check.size() && check[i+1]>=check[i+2]))
{
check[i+1]--;
}
}
}
int res = 0;
for(int i = check.size()-1;i>0;i--)
{
if(check[i-1]< check[i])
{
check[i-1] = check[i];
}
res *= 10;
res += check[i];
}
res *= 10;
res += check[0];
return res;
}
};
代码随想录中给出了另外一种方法,那就是如果遇到低位比高位大的情况,先将低位–,然后记录此时高位的位置。待一次遍历结束后,从记录的位置向高位赋值9。
//统计每个位的字符
//然后按个位 十位这样组成一个数组
//如果i<i+1那么将nums[i]变为9
//接着比较i+1>=i+2 或者 i+1是否是最后一个 nums[i+1] -1
//最后在从右向左遍历,如果后遍历比前遍历的小则修改
class Solution {
public:
int monotoneIncreasingDigits(int n) {
if(n ==0) return 0;
vector<int> check;
while(n)
{
int temp = n%10;
check.push_back(temp);
n = n/10;
}
//记录当前的第一个需要更改的位置
int flag = -1;
for(int i = 0;i<check.size()-1;i++)
{
if(check[i+1] > check[i])
{
flag = i;
check[i+1]--;
}
}
for(int i = flag;i>=0;i--)
{
check[i] = 9;
}
int res = 0;
for(int i = check.size()-1;i>=0;i--)
{
res *= 10;
res += check[i];
}
return res;
}
};
968.监控二叉树
文档讲解:代码随想录
视频讲解: 贪心算法,二叉树与贪心的结合,有点难… LeetCode:968.监督二叉树
状态
本题首先需要考虑的是摄像头该如何放置,为了使得摄像头最少,那么在叶子节点上就不应该放置摄像头,而应当在叶子节点的父节点上放置。
接着就是采用后序遍历,应为我们要根据子结点的放置来判断中间节点的放置情况。
对于一个节点来说总共可能出现3种情况
没有被覆盖 – 0
作为摄像头节点 – 1
作为被覆盖节点 – 2
现在来考虑返回值,当我们遇见空节点时,空节点只能作为被覆盖节点即返回2,因为首先空节点不能作为摄像头节点,其次如果其没有被覆盖,那么叶子节点一定有摄像头
if(root == nullptr) return 2;
最后就是单层逻辑的处理
- 如果左右节点都是被覆盖节点 返回值为2
那么此时的中间节点应当为0, - 如果左右节点至少有一个无覆盖的情况 返回值为0
那么中间节点应当放置一个摄像头 应当为1
- 左右节点至少有一个摄像头, 即有一个返回值为1
那么 中间节点应当为2
- 对根节点需要单独判断
如果根节点没有被覆盖,那么就需要再增加一个摄像头。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
private:
int res = 0;
public:
int SetCamera(TreeNode* root)
{
//空节点
if(root == nullptr) return 2;
int left = SetCamera(root->left);
int right = SetCamera(root->right);
//如果左右节点都是 2
if(left == 2 && right ==2)
{
return 0;
}
//如果左右节点有一个是没有被覆盖
if(left == 0|| right == 0)
{
res++;
return 1;
}
//如果左右节点有一个是摄像头,返回1
if(left == 1 || right == 1)
{
return 2;
}
return -1;
}
public:
int minCameraCover(TreeNode* root) {
if(SetCamera(root) == 0)
{
res++;
}
return res;
}
};