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

一、前言:

参考文献:代码随想录

今天主要考察的是贪心,今天只有两道题目,但是都比较的难,所以我们一起来细看一下吧!

二、单调递增的数字

1、思路:

本题目的思路比较简单,就是只要找到比所给数字小,且在每一位都单调递增的数字即可;

但是实现起来却很麻烦。

首先是暴力思路:

cpp 复制代码
class Solution {
private:
    bool checkNum(int num) {
        int max = 10;
        while (num) {
            int tmp = num % 10;
            if (max >= tmp) max = tmp;
            else return false;
            num = num / 10;
        }
        return true;
    }
public:
    int monotoneIncreasingDigits(int n) {
        for (int i = n; i >= 0; i--) {
            if (checkNum(i)) return i;
        }
        return 0;
    }
};

时间复杂度为O(n * m),n,m为数字长度;

这个解法是超时的;

然后这里的贪心思路就是:

(1)将数字转化为字符串形式,然后进行从后往前的遍历;

(2)在遍历的过程中去贪心,前一个数字比后一个数字大的话就把前一个数字减1,然后后一个数字变成9;

(3)通过这种贪心算法就可实现O(n)时间复杂度的解答;

2、整体代码如下:

cpp 复制代码
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        // 将数字转化为字符串
        string strNum = to_string(n);
        // 用于记录变成9的那一位
        int flag = strNum.size();
        for (int i = strNum.size() - 1; i  > 0; i--) { // 从后往前遍历
            if (strNum[i - 1] > strNum[i]) {
                strNum[i - 1]--;
                flag = i;
            }
        }
        for (int i = flag; i < strNum.size(); i++) {
            strNum[i] = '9';
        }
        return stoi(strNum);
    }
};

三、监控二叉树

1、思路:

这一题的思路比较复杂:

首先我们需要知道节点的状态有哪几种:

(1)覆盖,没被覆盖,有摄像头

(2)接着我们需要理清楚一共有几种情况:

1、左右子树都有覆盖的话,父节点就没覆盖了

2、左子树或者右子树有一个没有覆盖的话,父节点就必须装摄像头了

3、左右子树只要有一个有摄像头,父节点就被覆盖了

4、返回的根节点root无覆盖的话,就给根节点装摄像头;

根据这些,我们可以发现使用后序遍历,然后再根节点上做操作,就可以完成这个结果的输出;

(3)在递归中,我们首先需要确定返回值和参数:

cpp 复制代码
    int traversal(TreeNode* node)

这里的int代表的就是每个结点的状态;

(4)终止条件:

cpp 复制代码
        if (node == NULL) return 2;

为什么时返回2呢?因为当遇到空节点时,就说明他的父亲节点是叶子节点,我们需要的是,叶子节点不装摄像头,才能节省摄像头的数量(这个逻辑想必想一想就能出来),所以要返回的是被覆盖,叶子节点才不会去装摄像头;

(5)接下来就是四种情况了;

2、整体代码如下:

cpp 复制代码
class Solution {
    /*
    节点分为三种状态:
    0:无覆盖
    1:摄像头
    2:有覆盖
    分别去判断,如果遍历的是NULL就返回2,因为叶子节点不需要转摄像头
    又分为四种状态:
    1、左右子树都有覆盖的话,父节点就没覆盖了
    2、左子树或者右子树有一个没有覆盖的话,父节点就必须装摄像头了
    3、左右子树只要有一个有摄像头,父节点就被覆盖了
    4、返回的根节点root无覆盖的话,就给根节点装摄像头;

    
    */
private:
    int result;
    int traversal(TreeNode* node) {
        if (node == NULL) return 2;
        // 采用后序遍历,遍历完叶子节点,才遍历根节点
        int left = traversal(node->left);
        int right = traversal(node->right);
        // 情况1
        if (left == 2 && right == 2) {
            return 0;
        }
        // 情况2
        if (left == 0 ||right == 0) {
            // 摄像头加1
            result++;
            return 1;
        }
        // 情况3
        if (left == 1 || right == 1) {
            return 2;
        }

        return -1;
    }
public:
    int minCameraCover(TreeNode* root) {
        result = 0;
        // 情况4
        if (traversal(root) == 0) result++;
        return result;
    }
};

今日学习时间:1.5小时

leave message:

Those who don't believe in magic will never find it.

那些不相信魔法的人永远找不到它。

相关推荐
地平线开发者2 小时前
J6B vio scenario sample
算法
Flittly9 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了9 小时前
Java 生成二维码解决方案
java·后端
BothSavage14 小时前
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
算法
小林ixn14 小时前
从暴力到KMP:一道题彻底搞懂字符串匹配的前世今生
算法
人活一口气14 小时前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
烬羽15 小时前
字符串算法入门:从反转字符串到回文判断,面试不再慌
算法·面试
NE_STOP15 小时前
Vibe Coding -- 完整项目案例实操
java
荣码16 小时前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python