day31|leetcode 56. 合并区间 , 738.单调递增的数字 , 968.监控二叉树

14.合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

示例 1:

复制代码
输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

思路

先将根据左边界从小到大将区间进行排序

然后直接把第一个区间插入result

这样result存的区间的左边界永远是最小的

只需根据是否重叠来更新右边界即可

cpp 复制代码
class Solution {
    static bool cmp(const vector<int>&a,const vector<int>&b)
    {
        return a[0]<b[0];
    }
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>>result;
        if(intervals.size()==0)return result;
        sort(intervals.begin(),intervals.end(),cmp);//根据左边界从小到大排序
        result.push_back(intervals[0]);//把第一个区间放进去,左边界一定是最小的
        for(int i=1;i<intervals.size();i++)
        {
            if(result.back()[1]>=intervals[i][0])//前一个区间的右边界大于后一个区间的左边界,说明重叠
            {
               result.back()[1]=max(result.back()[1],intervals[i][1]);//只需更新右边界
            }
            else
            {
               result.push_back(intervals[i]);//不重叠就直接放进去
            }
        }
        return result;
    }
};
  • 时间复杂度: O(nlogn)快排

  • 空间复杂度: O(logn),排序需要的空间开销

15.单调递增的数字

当且仅当每个相邻位数上的数字 xy 满足 x <= y 时,我们称这个整数是单调递增的。

给定一个整数 n ,返回 小于或等于 n 的最大字,且数字呈 单调递增

示例 2:

复制代码
输入: n = 1234
输出: 1234

示例 3:

复制代码
输入: n = 332
输出: 299

贪心思路

从后往前遍历,如果前一位数大于后一位就把前一位数一直减,直到前一位小于等于后一位,然后把后一位设置为9

例如:332--->(3<2,3--)--->322(2-->9)--->329(3>2-->3--)--->229(2-->9)--->299

cpp 复制代码
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string strNUm  = to_string(n);
        int flag = strNUm.size();//用来记录从哪里开始变9
        for(int i=strNUm.size()-1;i>0;i--)
        {
            if(strNUm[i-1]>strNUm[i])
            {
                flag=i;//记录要变成9的位置
                strNUm[i-1]--;
            }
        }
        for(int i=flag;i<strNUm.size();i++)//flag记录的是最先开始变成9的位置
        {
            strNUm[i]='9';
        }
        return stoi(strNUm);//变数字
    }
};

时间复杂度:O(n),n 为数字长度

空间复杂度:O(n),需要一个字符串


16.监控二叉树

给定一个二叉树,我们在树的节点上安装摄像头。

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

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

(困难)

贪心思路

叶子节点不放摄像头,因为没有子节点给叶子节点监控。监控放父节点

难点 :节点上的每个摄影头都可以监视其父对象、自身及其直接子对象,如何跳过两个节点放摄像头

假设0:无覆盖,1:有摄像头,2:有覆盖

要装摄像头的不同的情况:

(1)左右孩子都有覆盖:

即左右孩子都是2

(2)左右孩子至少一个有覆盖

(3)左右孩子至少有一个有摄像头:

此时父节点一定是有覆盖的状态

(4)利用后序遍历,从小往上遍历,如果遍历完了,根节点还是无覆盖状态就在根节点放一个摄像头

cpp 复制代码
/**
 * 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 {
public:
    int result=0;
    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:左右至少有一个没被监控到
        // 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:左右均已被监控
        if(left==1 || right==1)
        {
            return 2;
        }
​
        return -1;//随便给个值,反正不会遍历到这里
    }
    int minCameraCover(TreeNode* root) {
        result=0;
        if(traversal(root)==0)//root没被监控到
        {
            result++;
        }
        return result;//traversal最终返回的是根节点是否被监控,result在遍历期间进行++
    }
};
复制代码
这题很难,下次我再做一遍,贪心结束啦!
相关推荐
涛ing9 分钟前
32. C 语言 安全函数( _s 尾缀)
linux·c语言·c++·vscode·算法·安全·vim
独正己身1 小时前
代码随想录day4
数据结构·c++·算法
我不是代码教父3 小时前
[原创](Modern C++)现代C++的关键性概念: 流格式化
c++·字符串格式化·流格式化·cout格式化
利刃大大4 小时前
【回溯+剪枝】找出所有子集的异或总和再求和 && 全排列Ⅱ
c++·算法·深度优先·剪枝
子燕若水4 小时前
mac 手工安装OpenSSL 3.4.0
c++
*TQK*4 小时前
ZZNUOJ(C/C++)基础练习1041——1050(详解版)
c语言·c++·编程知识点
Rachela_z4 小时前
代码随想录算法训练营第十四天| 二叉树2
数据结构·算法
细嗅蔷薇@4 小时前
迪杰斯特拉(Dijkstra)算法
数据结构·算法
追求源于热爱!4 小时前
记5(一元逻辑回归+线性分类器+多元逻辑回归
算法·机器学习·逻辑回归
ElseWhereR5 小时前
C++ 写一个简单的加减法计算器
开发语言·c++·算法