代码随想录打卡|Day27(合并区间、单调递增的数字、监控二叉树)

贪心算法 Part05

合并区间

力扣题目链接
代码随想录链接
视频讲解链接

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

思路:对于这道题目,我们只需要按照每个区间的左边界进行从小到大排序,随后依次遍历每个区间,获取他们的范围,将范围有重叠的区间合并(取重叠区间的最小做区间和最大右区间的值),并将合并后得出的每个区间的范围重新记录,最后输出即可。

代码如下:

java 复制代码
class Solution {
    public int[][] merge(int[][] intervals) {
        
        // Arrays.sort(intervals,(a,b) -> a[0] - b[0]);
        Arrays.sort(intervals,(a,b) -> Integer.compare(a[0],b[0]));

        int start = intervals[0][0] ;
        int end = intervals[0][1];
        List<int[]> res = new LinkedList<>();
        for(int i = 1 ; i < intervals.length ; i++){
            if(intervals[i][0] <= end){
                start = Math.min(start , intervals[i][0]);
                end = Math.max(end , intervals[i][1]);
            }else{
                res.add(new int[]{start , end});
                start = intervals[i][0];
                end = intervals[i][1];
            }
        }
        res.add(new int[]{start , end});
        return res.toArray(new int[res.size()][]);
    }
}

代码随想录代码:

java 复制代码
/**
时间复杂度 : O(NlogN) 排序需要O(NlogN)
空间复杂度 : O(logN)  java 的内置排序是快速排序 需要 O(logN)空间

*/
class Solution {
    public int[][] merge(int[][] intervals) {
        List<int[]> res = new LinkedList<>();
        //按照左边界排序
        Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0]));
        //initial start 是最小左边界
        int start = intervals[0][0];
        int rightmostRightBound = intervals[0][1];
        for (int i = 1; i < intervals.length; i++) {
            //如果左边界大于最大右边界
            if (intervals[i][0] > rightmostRightBound) {
                //加入区间 并且更新start
                res.add(new int[]{start, rightmostRightBound});
                start = intervals[i][0];
                rightmostRightBound = intervals[i][1];
            } else {
                //更新最大右边界
                rightmostRightBound = Math.max(rightmostRightBound, intervals[i][1]);
            }
        }
        res.add(new int[]{start, rightmostRightBound});
        return res.toArray(new int[res.size()][]);
    }
}

单调递增的数字

力扣题目链接
代码随想录链接
视频讲解链接

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

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

思路:将数组转换成为字符串再转换为数组,从尾到头判断两个相邻数字的大小是否满足递增,若不满足,前一个数字减一,后一个数字变成9.

代码如下:

java 复制代码
class Solution {
    public int monotoneIncreasingDigits(int n) {
        String str = String.valueOf(n);
        char[] strArray = str.toCharArray();
        // 记录需要变成9的数字开始下标
        int index = strArray.length;
        for(int i = strArray.length - 2; i >= 0 ; i--){
            if(strArray[i] > strArray[i + 1]){
                strArray[i] --;
                index = i + 1;
            }
        }

        for(int i = index ; i < strArray.length ; i++)
            strArray[i] = '9';
        return Integer.parseInt(String.valueOf(strArray));
    }
}

另一种方法(创建了String数组,多次使用Integer.parseInt了方法,这导致不管是耗时还是空间占用都非常高,用时12ms)

java 复制代码
class Solution {
    public int monotoneIncreasingDigits(int N) {
        String[] strings = (N + "").split("");
        int start = strings.length;
        for (int i = strings.length - 1; i > 0; i--) {
            if (Integer.parseInt(strings[i]) < Integer.parseInt(strings[i - 1])) {
                strings[i - 1] = (Integer.parseInt(strings[i - 1]) - 1) + "";
                start = i;
            }
        }
        for (int i = start; i < strings.length; i++) {
            strings[i] = "9";
        }
        return Integer.parseInt(String.join("",strings));
    }
}

监控二叉树

力扣题目链接
代码随想录链接
视频讲解链接

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

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

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

思路:对于二叉树的题目,使用递归解决问题的时候需要考虑是应该使用前中后哪一种顺序。在本题目之中,我们需要使用最少数量的摄像头覆盖二叉树的所有节点,那么我们就一定不能在叶子节点部署摄像头,所以我们需要隔层安放摄像头。

基于此,我们对每个节点定义三种状态:

0:该节点没有被摄像头覆盖

1:该节点安放摄像头

2:该节点被摄像头覆盖

所以,对于一个非叶子节点,他的状态会存在三种:

1.该节点的两个叶子节点被覆盖,该节点就应该先赋值为0;

2.该节点的左节点或者右节点为0,则说明该节点必须安装摄像头。

3.该节点的至少一个叶子节点安装摄像头,则该节点应该被标记为2(被覆盖)。

此外,递归结束之后,root节点的值可能还会出现为0的情况,需要单独处理,若递归函数返回值为0,则摄像头的数量应该+1;

代码如下:

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int result = 0;
    public int minCameraCover(TreeNode root) {
        // if(root.left == null && root.right == null) return 1;
        // 还会存在root节点为0的情况,因此,需要再次判断
        if(minCameraCounter(root)==0) result++;
        return result;
    }
    /**
     节点的状态值:
       0 表示无覆盖
       1 表示 有摄像头
       2 表示有覆盖
    后序遍历,根据左右节点的情况,来判读 自己的状态
     */

    // 1.确定递归函数的返回类型和传入参数类型
    private int minCameraCounter(TreeNode node){
        // 确定递归函数的结束条件
        // 1.当节点为叶子节点的时候,我们应该将他的值赋值为2
        if(node == null) return 2;

        // left
        int left = minCameraCounter(node.left);
        // right
        int right = minCameraCounter(node.right);

        // 情况1:当节点的左右孩子的值均为2,则证明节点不用部署摄像头
        if(left == 2 && right == 2){ 
            return 0;
        }
        // 情况2:当节点的左孩子或右孩子的值为0的时候,就代表该节点应该部署摄像头
        if(left == 0 || right == 0){
            result++;
            return 1;
        }
        // 情况3:当节点的左右孩子至少存在一个摄像头的时候,那么该节点的就应该是被覆盖了
        else{
            return 2;
        }
    }
}

相关推荐
莹莹学编程—成长记1 小时前
string的模拟实现
服务器·c++·算法
lybugproducer1 小时前
创建型设计模式之:简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式
java·设计模式·建造者模式·简单工厂模式·工厂方法模式·抽象工厂模式·面向对象
南客先生1 小时前
马架构的Netty、MQTT、CoAP面试之旅
java·mqtt·面试·netty·coap
Minyy111 小时前
SpringBoot程序的创建以及特点,配置文件,LogBack记录日志,配置过滤器、拦截器、全局异常
xml·java·spring boot·后端·spring·mybatis·logback
百锦再1 小时前
Java与Kotlin在Android开发中的全面对比分析
android·java·google·kotlin·app·效率·趋势
武昌库里写JAVA2 小时前
39.剖析无处不在的数据结构
java·vue.js·spring boot·课程设计·宠物管理
Nelson_hehe5 小时前
Java基础第四章、面向对象
java·语法基础·面向对象程序设计
Thomas_YXQ5 小时前
Unity3D Lua集成技术指南
java·开发语言·驱动开发·junit·全文检索·lua·unity3d
东阳马生架构7 小时前
Nacos简介—3.Nacos的配置简介
java