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在遍历期间进行++
    }
};
复制代码
这题很难,下次我再做一遍,贪心结束啦!
相关推荐
云里雾里!7 分钟前
LeetCode 744. 寻找比目标字母大的最小字母 | 从低效到最优的二分解法优化
算法·leetcode
fy zs7 分钟前
网络编程套接字
linux·服务器·网络·c++
fpcc9 分钟前
模板编程—模板和元编程中的错误输出
c++·模板编程
xie_pin_an11 分钟前
C++ 类和对象全解析:从基础语法到高级特性
java·jvm·c++
小温冲冲15 分钟前
C++与QML信号绑定完全指南:实现跨语言无缝通信
c++
GIS 数据栈20 分钟前
【Seggis遥感系统升级】用C++高性能服务Drogon重构软件服务架构|QPS提升300%,性能再升级!
java·开发语言·c++·重构·架构
一条大祥脚21 分钟前
26.1.3 快速幂+容斥 树上dp+快速幂 带前缀和的快速幂 正序转倒序 子序列自动机 线段树维护滑窗
数据结构·算法
二狗哈26 分钟前
czsc入门5: Tick RawBar(原始k线) NewBar (新K线)
算法·czsc
Tisfy31 分钟前
LeetCode 0865.具有所有最深节点的最小子树:深度优先搜索(一次DFS + Python5行)
算法·leetcode·深度优先·dfs·题解
王老师青少年编程33 分钟前
信奥赛C++提高组csp-s之二分图
数据结构·c++·二分图·csp·信奥赛·csp-s·提高组