代码随想录Day37 | 738.单调递增的数字 968.监控二叉树

代码随想录Day37 | 738.单调递增的数字 968.监控二叉树

  • 738.单调递增的数字
  • 968.监控二叉树

738.单调递增的数字

文档讲解:代码随想录
视频讲解: 贪心算法,思路不难想,但代码不好写!LeetCode:738.单调自增的数字
状态

本题可以通过比较低位与高位,如果低位比高位小,则变为9,同时比较高位的高位,如果高位比高位的高位大,那么就–。遍历完一次后,再从高位向低位遍历,如果高位比低位大,那么修改低位的值为高位的值

//统计每个位的字符
//然后按个位 十位这样组成一个数组
//如果i=i+2 或者 i+1是否是最后一个 nums[i+1] -1
//最后在从右向左遍历,如果后遍历比前遍历的小则修改
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        if(n ==0) return 0;
        vector check;
        while(n)
        {
            int temp = n%10;
            check.push_back(temp);
            n = n/10;
        }
        for(int i = 0;i=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+2 或者 i+1是否是最后一个 nums[i+1] -1
//最后在从右向左遍历,如果后遍历比前遍历的小则修改
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        if(n ==0) return 0;
        vector check;
        while(n)
        {
            int temp = n%10;
            check.push_back(temp);
            n = n/10;
        }
        //记录当前的第一个需要更改的位置
        int flag = -1;
        for(int i = 0;i 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
    代码随想录Day37 | 738.单调递增的数字 968.监控二叉树_第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;
    }
};

你可能感兴趣的:(算法)