代码随想录算法训练营第37天| Leetcode 738.单调递增的数字、968.监控二叉树

Leetcode 738.单调递增的数字

题目链接:Leetcode 738.单调递增的数字
题目描述: 当且仅当每个相邻位数上的数字 xy 满足 x <= y 时,我们称这个整数是单调递增的。

给定一个整数 n ,返回 小于或等于n的最大数字,且数字呈单调递增 。
思路: 本题数据范围太大了,暴力解法肯定会超时,因此需要借助贪心思想优化。

  1. 如果是0~9的话返回其本身,也就是不需要任何操作
  2. 如果是10~99,我们可以判断十位数字与个位数字的大小,比如73,我们需要做的操作就是7--,然后3变成9,结果为69
  3. 对于三位数及以上数字,可以从后两位开始判断,将其变为单调递增数字(局部最优),再逐渐判断更高一位的数字,最终数字整体变成单调递增数字(全局最优)。

基于以上思路,我们可以发现从后向前遍历数字更适合。这里还有一个小技巧:可以将数字转换成字符串,这样可以轻松获得每一位上的数字。 尽管这样增加了空间复杂度,但是代码更好写了。

代码如下:

class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string s = to_string(n);//字符串更方便操作每一位上的数字
        //用flag标记从哪个位置之后全赋值为9
        int flag = s.size();
        for (int i = s.size() - 1; i > 0; i--) {
            if (s[i - 1] > s[i]) {
                flag = i;
                s[i - 1]--;
            }
        }
        for (int i = flag; i < s.size(); i++) {
            s[i] = '9';
        }
        return stoi(s);
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

Leetcode 968.监控二叉树

题目链接:Leetcode 968.监控二叉树
题目描述: 给定一个二叉树,我们在树的节点上安装摄像头。

节点上的每个摄影头都可以监视其父对象、自身及其直接子对象

计算监控树的所有节点所需的最小摄像头数量。

思路: 本题可以利用贪心思想,由于二叉树自上向下的节点个数是以指数级别增长,也就是说我们需要尽可能的让摄像头向上放而不聚集在叶子节点,这样可以节省大量摄像头数量,对应的我们需要利用二叉树的后序遍历,只有这样才是从下向上的判断是否需要添加摄像头。

代码如下:

class Solution {
public:
    int result; //统计摄像头数量
    // 0代表无覆盖,1代表摄像头,2代表有覆盖
    int traversal(TreeNode* cur) {
        //空节点,假设为有覆盖
        if (cur == nullptr)
            return 2;
        int left = traversal(cur->left);
        int right = traversal(cur->right);
        //(1)左右孩子都为2,则父节点为0
        if (left == 2 && right == 2)
            return 0;
        //(2)左右孩子至少有一个为0,则父节点为1
        // 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) {
            result++;
            return 1;
        }
        //(3)左右孩子至少有一个为1,则父节点为2
        if (left == 1 || right == 1)
            return 2;
        //所有情况已经讨论结束,但是没有这段代码leetcode编译不过
        return -1;
    }
    int minCameraCover(TreeNode* root) {
        result = 0;
        //不要漏掉这里:(4)回溯到最后可能根节点未被覆盖
        if (traversal(root) == 0)
            result++;
        return result;
    }
};
  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

这道题官方题解是动态规划,代码执行的行为类似,不过我感觉还是这种分类讨论+贪心的方法好理解。


总结: 贪心类题目多积累吧,遇到新题目没思路确实不好搞。

最后,如果文章有错误,请在评论区或私信指出,让我们共同进步!

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值