day31| 56. 合并区间 738.单调递增的数字 968.监控二叉树 (可跳过)

代码随想录算法训练营第31天| 56. 合并区间 738.单调递增的数字 968.监控二叉树 (可跳过)

Leetcode 56. 合并区间
题目链接:https://leetcode.cn/problems/merge-intervals/description/
题目描述:

以数组 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].

示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

  • 1 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 104
思路:贪心
代码1:
class Solution {
    public int[][] merge(int[][] intervals) {
        List<int[]> res = new LinkedList<>();
        // 按照左边界排序
        Arrays.sort(intervals,(a,b)->
            Integer.compare(a[0],b[0])
        );
        // 最小左边界
        int start = intervals[0][0];
        // 右边界
        int right = intervals[0][1];
        for(int i = 1 ; i < intervals.length ; i++){
            // 当左边界大于最大右边界
            if(intervals[i][0] > right){
                // 加入区间
                res.add(new int[]{start,right});
                // 更新左边界start
                start = intervals[i][0];
                right = intervals[i][1];

            }else{
                // 更大的右边界,有重叠部分
                right = Math.max(right,intervals[i][1]);
            }
        }
        res.add(new int[]{start,right});
        return res.toArray(new int[res.size()][]);
    }
}
Leetcode 738.单调递增的数字
题目链接:https://leetcode.cn/problems/monotone-increasing-digits/description/
题目描述:

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

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

示例 1:

输入: n = 10
输出: 9

示例 2:

输入: n = 1234
输出: 1234

示例 3:

输入: n = 332
输出: 299

提示:

  • 0 <= n <= 109
思路:贪心
代码1:
class Solution {
    public int monotoneIncreasingDigits(int n) {
        //将n转为字符串
        String s = String.valueOf(n);
        char[] chars = s.toCharArray();
        int start = s.length();
        for(int i = s.length() - 2 ; i >= 0 ; i--){
            if(chars[i] > chars[i + 1]){
                chars[i]--;
                start = i + 1;
            }
        }
        for(int i = start ; i < s.length() ; i++){
            chars[i] = '9';
        }
        return Integer.parseInt(String.valueOf(chars));
    }
}
代码2:
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));
    }
}
总结:
Leetcode 968.监控二叉树 (可跳过)
题目链接:https://leetcode.cn/problems/binary-tree-cameras/description/
题目描述:

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

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

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

示例 1:

img

输入:[0,0,null,0,0]
输出:1
解释:如图所示,一台摄像头足以监控所有节点。

示例 2:

img

输入:[0,0,null,0,null,0,null,null,0]
输出:2
解释:需要至少两个摄像头来监视树的所有节点。 上图显示了摄像头放置的有效位置之一。

提示:

  1. 给定树的节点数的范围是 [1, 1000]
  2. 每个节点的值都是 0。
思路:贪心
代码1:
/**
 * 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 res = 0;
    public int minCameraCover(TreeNode root) {
        // 后序遍历

        // 节点有三种状态
        // 1、该节点无覆盖 0 
        // 2、该节点有摄像头 1
        // 3、本节点被覆盖 2

        // 空节点属于有覆盖状态

        // 主要有四种情况

        // 1、左右节点都有覆盖
        // 左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。
       
        // 2、左右只有一个无覆盖
        //有一个孩子没有覆盖,父节点就应该放摄像头。
        
        // 3、左右节点至少有一个有摄像头
        // 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)

        // 4、头结点没有覆盖


        
        // 对根节点进行检验,防止根节点是无覆盖状态
        if(minCame(root) == 0){
            res++;
        }
        return res;
    }
        // 节点有三种状态
        // 1、该节点无覆盖 0 
        // 2、该节点有摄像头 1
        // 3、本节点被覆盖 2

        public int minCame(TreeNode root){
            if(root == null){
                // 空节点默认为 有覆盖状态,避免在叶子节点上放摄像头
                return 2;
            }
            int left = minCame(root.left);
            int right = minCame(root.right);

            // 如果左右节点都覆盖,那么此时中间节点应该就是无覆盖的状态了。
            if(left == 2 && right == 2){
                return 0;
            }else if(left == 0 || right == 0){
                // 左右节点都是无覆盖状态,那 根节点此时应该放一个摄像头
                // (0,0) (0,1) (0,2) (1,0) (2,0)
                // 状态值为 1 摄像头数 ++;
                res++;
                return 1;
            }else{
                 // 左右节点的 状态为 (1,1) (1,2) (2,1) 也就是左右节点至少存在 1个摄像头,
                // 那么本节点就是处于被覆盖状态
                return 2;
            }
        }
    }





(2,0)
// 状态值为 1 摄像头数 ++;
res++;
return 1;
}else{
// 左右节点的 状态为 (1,1) (1,2) (2,1) 也就是左右节点至少存在 1个摄像头,
// 那么本节点就是处于被覆盖状态
return 2;
}
}
}


###### 

###### 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值