• LeetCode——贪心篇(三)


    目录

    452. 用最少数量的箭引爆气球

    435. 无重叠区间

    763. 划分字母区间

    56. 合并区间

    738. 单调递增的数字

    968. 监控二叉树


    刷题顺序及思路来源于代码随想录,网站地址https://programmercarl.com

    452. 用最少数量的箭引爆气球

    有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

    一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstartxend, 且满足  xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

    给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 

    1. 输入:points = [[10,16],[2,8],[1,6],[7,12]]
    2. 输出:2
    3. 解释:气球可以用2支箭来爆破:
    4. -在x = 6处射出箭,击破气球[2,8]和[1,6]。
    5. -在x = 11处发射箭,击破气球[10,16]和[7,12]。
    1. import java.util.Arrays;
    2. import java.util.Comparator;
    3. /**
    4. * @author light
    5. * @Description 452. 用最少数量的箭引爆气球
    6. *
    7. *
    8. * (思路:重叠在一起的气球用一只箭射出,
    9. * 但要注意重叠的右区间:如果下一个气球的左边界小于上一个重叠区间最小的右边界,则这个气球可以被同一只箭引爆
    10. * @create 2023-09-09 8:25
    11. */
    12. public class FindMinArrowShotsTest {
    13. public static void main(String[] args) {
    14. int[][] points={{10,6},{2,8},{1,6},{7,12}};
    15. System.out.println(findMinArrowShots(points));
    16. }
    17. public static int findMinArrowShots(int[][] points) {
    18. //先将气球按最左区间从小到大排序
    19. //int 范围为-2147483648——2147483647,测试案例中会溢出
    20. Arrays.sort(points, new Comparator<int[]>() {
    21. @Override
    22. public int compare(int[] o1, int[] o2) {
    23. //return o1[0]-o2[0];
    24. return Integer.compare(o1[0],o2[0]); //采用Integer.compare()不会溢出
    25. }
    26. });
    27. int count=1; //气球不为空则至少需要一只箭
    28. for (int i = 1; i < points.length; i++) {
    29. if(points[i][0]>points[i-1][1]){
    30. count++;
    31. }else {
    32. points[i][1]=Math.min(points[i][1],points[i-1][1]);
    33. }
    34. }
    35. return count;
    36. }
    37. }

    435. 无重叠区间

    给定一个区间的集合 intervals ,其中 intervals[i] = [starti, endi] 。返回 需要移除区间的最小数量,使剩余区间互不重叠 

    1. 输入: intervals = [[1,2],[2,3],[3,4],[1,3]]
    2. 输出: 1
    3. 解释: 移除 [1,3] 后,剩下的区间没有重叠。
    1. import java.util.Arrays;
    2. import java.util.Comparator;
    3. /**
    4. * @author light
    5. * @Description 无重叠区间
    6. *
    7. *
    8. * @create 2023-09-10 10:41
    9. */
    10. public class EraseOverlapIntervalsTest {
    11. public static void main(String[] args) {
    12. int[][] intervals={{1,2},{2,3},{3,4},{1,3}};
    13. System.out.println(eraseOverlapIntervals(intervals));
    14. }
    15. public static int eraseOverlapIntervals(int[][] intervals) {
    16. //先将数组按左边界排序
    17. Arrays.sort(intervals, new Comparator<int[]>() {
    18. @Override
    19. public int compare(int[] o1, int[] o2) {
    20. return Integer.compare(o1[0],o2[0]);
    21. }
    22. });
    23. int count=0;//记录重叠区间数
    24. for (int i = 1; i < intervals.length; i++) {
    25. if(intervals[i][0]<intervals[i-1][1]){ //判断重叠情况
    26. count++;
    27. intervals[i][1]=Math.min(intervals[i][1],intervals[i-1][1]);
    28. }
    29. }
    30. return count;
    31. }
    32. }

    763. 划分字母区间

    给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

    注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。

    返回一个表示每个字符串片段的长度的列表。

    1. 输入:s = "ababcbacadefegdehijhklij"
    2. 输出:[9,7,8]
    3. 解释:
    4. 划分结果为 "ababcbaca""defegde""hijhklij"
    5. 每个字母最多出现在一个片段中。
    6. "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。
    1. import java.util.ArrayList;
    2. import java.util.List;
    3. import java.util.Scanner;
    4. /**
    5. * @author light
    6. * @Description 划分字母区间
    7. *
    8. * (思路:遍历字符串,找到每个字符的最远下标
    9. * @create 2023-09-10 11:07
    10. */
    11. public class PartitionLabelsTest {
    12. public static void main(String[] args) {
    13. Scanner input=new Scanner(System.in);
    14. String s=input.next();
    15. System.out.println(partitionLabels(s));
    16. }
    17. public static List partitionLabels(String s) {
    18. List list=new ArrayList<>(); //定义结果集
    19. int[] edge=new int[27]; //存放元素最远下标
    20. char[] arr=s.toCharArray();
    21. for (int i = 0; i < arr.length; i++) {
    22. edge[arr[i]-'a']=i;
    23. }
    24. int idx=0;
    25. int end=0;
    26. for (int i = 0; i < arr.length; i++) {
    27. idx=Math.max(idx,edge[arr[i]-'a']); //找到最远下标
    28. if(i==idx){
    29. list.add(idx-end+1); //将长度加入集合中
    30. end=i+1;
    31. }
    32. }
    33. return list;
    34. }
    35. }

    56. 合并区间

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

    1. 输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
    2. 输出:[[1,6],[8,10],[15,18]]
    3. 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
    1. public static int[][] merge(int[][] intervals) {
    2. List<int[]> list=new ArrayList<>();
    3. //将数组按左边界排序
    4. Arrays.sort(intervals, new Comparator<int[]>() {
    5. @Override
    6. public int compare(int[] o1, int[] o2) {
    7. return Integer.compare(o1[0],o2[0]);
    8. }
    9. });
    10. for (int i = 1; i < intervals.length; i++) {
    11. if(intervals[i][0]<=intervals[i-1][1]){
    12. //有重叠,合并区间---求右边界最大值,左区间最小值
    13. intervals[i][1]=Math.max(intervals[i-1][1],intervals[i][1]);
    14. intervals[i][0]=Math.min(intervals[i-1][0],intervals[i][0]);
    15. }else {
    16. list.add(intervals[i-1]);
    17. }
    18. }
    19. list.add(intervals[intervals.length-1]);
    20. return list.toArray(new int[list.size()][]);
    21. }

    738. 单调递增的数字

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

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

    1. 输入: n = 10
    2. 输出: 9
    1. import java.util.Scanner;
    2. /**
    3. * @author light
    4. * @Description 单调递增的数字
    5. *
    6. * (思路:从后向前遍历数字,当遇到Num[i]
    7. * @create 2023-09-10 13:40
    8. */
    9. public class MonotoneIncreasingDigitsTest {
    10. public static void main(String[] args) {
    11. Scanner input=new Scanner(System.in);
    12. int n=input.nextInt();
    13. System.out.println(monotoneIncreasingDigits(n));
    14. }
    15. public static int monotoneIncreasingDigits(int n) {
    16. String s=String.valueOf(n);
    17. char[] arr=s.toCharArray();
    18. int flag=arr.length;
    19. for (int i =arr.length-1; i >0; i--) {
    20. if(arr[i-1]>arr[i]){
    21. arr[i-1]--;
    22. flag=i; //记录要变为9的下标起始位置
    23. }
    24. }
    25. for (int i = flag; i < arr.length; i++) {
    26. arr[i]='9';
    27. }
    28. return Integer.parseInt(String.valueOf(arr));
    29. }
    30. }

    968. 监控二叉树

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

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

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

     

    1. int count=0;
    2. public int minCameraCover(TreeNode root) {
    3. if(minCamera(root)==0){ //对根节点进行校验,防止根节点无覆盖
    4. count++;
    5. }
    6. return count;
    7. }
    8. private int minCamera(TreeNode root) {
    9. if(root==null){
    10. return 2; //空节点---有覆盖
    11. }
    12. //左
    13. int left=minCamera(root.left);
    14. //右
    15. int right=minCamera(root.right);
    16. //中
    17. //1.左右孩子都有覆盖---中间父节点无覆盖
    18. if(left==2&&right==2){
    19. return 0;
    20. }else if(left==0||right==0){
    21. // 2.左右孩子至少一个无覆盖---中间结点父放摄像头
    22. count++;
    23. return 1;
    24. } else {
    25. // 3.左右孩子有一个有摄像头---中间父节点有覆盖
    26. return 2;
    27. }
    28. }

  • 相关阅读:
    IDEA 中如何通过连接数据库自动生成代码
    【数据结构C/C++】多维数组的原理、访问方式以及作用
    一小时上手MindSpore
    嵌入式系统,内存不够了该怎么办?
    SpringMVC 02
    Kotlin 基础学习 (一) 关键字
    【数据结构】链表中二级指针的应用
    【数据结构】单链表详解
    代码规范常见错误
    CF1152F Neko Rules the Catniverse(状压 DP)
  • 原文地址:https://blog.csdn.net/zssxcj/article/details/132776938