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在遍历期间进行++
    }
};
复制代码
这题很难,下次我再做一遍,贪心结束啦!
相关推荐
GISer_Jing10 分钟前
[3D GIS&Mesh]三角网格模型中的孔洞修补算法
算法·3d
姬公子52125 分钟前
leetcode hot100刷题日记——34.将有序数组转换为二叉搜索树
算法·leetcode·深度优先
笑口常开xpr26 分钟前
LeetCode 算 法 实 战 - - - 移 除 链 表 元 素、反 转 链 表
算法·leetcode·链表
姬公子52131 分钟前
leetcode hot100刷题日记——33.二叉树的层序遍历
算法·leetcode·职场和发展
编程绿豆侠33 分钟前
力扣HOT100之动态规划:152. 乘积最大子数组
算法·leetcode·动态规划
月亮被咬碎成星星33 分钟前
LeetCode[110]平衡二叉树
算法·leetcode
bigstrength44 分钟前
AtCoder Beginner Contest 407 E - Most Valuable Parentheses
算法
fouen1 小时前
贪心算法实战3
数据结构·算法·贪心算法
十五年专注C++开发1 小时前
Qt程序添加调试输出窗口:CONFIG += console
开发语言·c++·qt
CodeWithMe1 小时前
【C/C++】chrono简单使用场景
c语言·开发语言·c++