面试经典150题——区间

文章目录

  • 1、汇总区间
    • [1.1 题目链接](#1.1 题目链接)
    • [1.2 题目描述](#1.2 题目描述)
    • [1.3 解题代码](#1.3 解题代码)
    • [1.4 解题思路](#1.4 解题思路)
  • 2、合并区间
    • [2.1 题目链接](#2.1 题目链接)
    • [2.2 题目描述](#2.2 题目描述)
    • [2.3 解题代码](#2.3 解题代码)
    • [2.4 解题思路](#2.4 解题思路)
  • 3、插入区间
    • [3.1 题目链接](#3.1 题目链接)
    • [3.2 题目描述](#3.2 题目描述)
    • [3.3 解题代码](#3.3 解题代码)
    • [3.4 解题思路](#3.4 解题思路)
  • 4、用最少数量的箭引爆气球
    • [4.1 题目链接](#4.1 题目链接)
    • [4.2 题目描述](#4.2 题目描述)
    • [4.3 解题代码](#4.3 解题代码)
    • [4.4 解题思路](#4.4 解题思路)

1、汇总区间

1.1 题目链接

点击跳转到题目位置

1.2 题目描述

给定一个 无重复元素 的 有序 整数数组 nums 。

返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字 x 。

列表中的每个区间范围 [a,b] 应该按如下格式输出:

  • "a->b" ,如果 a != b
  • "a" ,如果 a == b

提示:

  • 0 <= nums.length <= 20
  • -2^31^ <= nums[i] <= 2^31^ - 1
  • nums 中的所有值都 互不相同
  • nums 按升序排列

1.3 解题代码

java 复制代码
class Solution {
    public List<String> summaryRanges(int[] nums) {
        int n = nums.length;
        int left = -1;
        int right = -1;
        List<String> ret = new ArrayList<String>();
        if(n == 0){
            return ret;
        }
        for(int i = 0; i < n; ++i){
            if(i == 0){
                left = nums[i];
                right = nums[i];
            } else{
                if(nums[i] == nums[i - 1] + 1){
                    right = nums[i];
                } else{
                    StringBuffer temp = new StringBuffer(); 
                    if(left == right){
                        temp.append(Integer.toString(left));
                        ret.add(temp.toString());            
                    } else{
                        temp.append(Integer.toString(left));
                        temp.append("->");
                        temp.append(Integer.toString(right));
                        ret.add(temp.toString());  
                    } 
                    left = nums[i];
                    right = nums[i];
                }
            }
        }
        StringBuffer temp = new StringBuffer(); 
        if(left == right){
            temp.append(Integer.toString(left));
            ret.add(temp.toString());            
        } else{
            temp.append(Integer.toString(left));
            temp.append("->");
            temp.append(Integer.toString(right));
            ret.add(temp.toString());  
        } 
    return ret;
    }
}

1.4 解题思路

  1. 直接从左往右遍历,获取区间left和right。i == 0的时候直接赋值left = right = nums[0]
  2. 当nums[i] == nums[i - 1] (i >= 1)时更新right,否则则将区间[left, right]放进字符串数组中,这个时候讨论 left 和 right 相等的情况。

2、合并区间

2.1 题目链接

点击跳转到题目位置

2.2 题目描述

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

提示:

  • 1 <= intervals.length <= 10^4^
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 10^4^

2.3 解题代码

java 复制代码
class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, new Comparator<int[]>(){
            public int compare(int[] interval1, int[] interval2){
                return interval1[0] - interval2[0];
            }
        });
        int n = intervals.length;
        int left = 0;
        int right = 0;

        List<int[]> merged = new ArrayList<int[]>();

        for(int i = 0; i < n; ++i){
            if(i == 0){
                left = intervals[i][0];
                right = intervals[i][1];
            } else{
                if(intervals[i][0] <= right){
                    right = Math.max(right, intervals[i][1]);
                } else{
                    merged.add(new int[]{left, right});
                    left = intervals[i][0];
                    right = intervals[i][1];
                }
            }
        }
        merged.add(new int[]{left, right});
    return merged.toArray(new int[merged.size()][]);
    }
}

2.4 解题思路

  1. 先将intervals按照区间左端点非递减进行排序
  2. 剩下的解题思路与第一题汇总区间一致,如果遍历到的左端点小于等于当前的维护区间右端点,则更新右端点为当前遍历端点的右端点和维护区间的右端点的最大值。否则将维护区间放入答案中,更新维护区间。

3、插入区间

3.1 题目链接

点击跳转到题目位置

3.2 题目描述

给你一个 无重叠的 ,按照区间起始端点排序的区间列表 intervals,其中 intervals[i] = [starti, endi] 表示第 i 个区间的开始和结束,并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval = [start, end] 表示另一个区间的开始和结束。

在 intervals 中插入区间 newInterval,使得 intervals 依然按照 starti 升序排列,且区间之间不重叠(如果有必要的话,可以合并区间)。

返回插入之后的 intervals。

注意 你不需要原地修改 intervals。你可以创建一个新数组然后返回它。

3.3 解题代码

java 复制代码
class Solution {
     public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, new Comparator<int[]>(){
            public int compare(int[] interval1, int[] interval2){
                return interval1[0] - interval2[0];
            }
        });
        int n = intervals.length;
        int left = 0;
        int right = 0;

        List<int[]> merged = new ArrayList<int[]>();

        for(int i = 0; i < n; ++i){
            if(i == 0){
                left = intervals[i][0];
                right = intervals[i][1];
            } else{
                if(intervals[i][0] <= right){
                    right = Math.max(right, intervals[i][1]);
                } else{
                    merged.add(new int[]{left, right});
                    left = intervals[i][0];
                    right = intervals[i][1];
                }
            }
        }
        merged.add(new int[]{left, right});
    return merged.toArray(new int[merged.size()][]);
    }

    public int[][] insert(int[][] intervals, int[] newInterval) {
        int n = intervals.length;
        int[][] ret = new int[n + 1][2];
        for(int i = 0; i < n; ++i){
            ret[i] = intervals[i];
        }
        ret[n] = newInterval;
    return merge(ret);
    }
}

3.4 解题思路

  1. 直接将区间和intervals插入进入新的数组中。
  2. 然后对这个新的数组进行合并期间即可。

4、用最少数量的箭引爆气球

4.1 题目链接

点击跳转到题目位置

4.2 题目描述

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

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

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

提示:

  • 1 <= points.length <= 10^5^
  • points[i].length == 2
  • -2^31^ <= xstart < xend <= 2^31^ - 1

4.3 解题代码

java 复制代码
class Solution {
    public int findMinArrowShots(int[][] points) {
        Arrays.sort(points, new Comparator<int[]>(){
            public int compare(int[] point1, int[] point2){
                if(point1[0] < point2[0]){
                    return -1;
                } else{
                    return 1;
                }
            } 
        });

        int n = points.length;
        for(int i = 0; i < n; ++i){
            System.out.println(points[i][0]);
        }
        int ret = 0;
        int left = -1;
        int right = -1;
        for(int i = 0; i < n; ++i){
            if(i == 0){
                left = points[i][0];
                right = points[i][1];
            } else{
                if(points[i][0] <= right){
                    left = Math.max(points[i][0], left);
                    right = Math.min(points[i][1], right);
                } else{
                    ret++;
                    left = points[i][0];
                    right = points[i][1];
                }
            }
        }
    return ret + 1;
    }
}

4.4 解题思路

  1. 跟合并区间一样的解题思路。
  2. 先对所有的点按照x坐标进行非递减排序
  3. 之后合并区间,不过取的是当前区间与维护区间的并集。如果没有并集就开枪,否则更新维护区间为两者的并集。
相关推荐
硕风和炜14 分钟前
【LeetCode: 112. 路径总和 + 二叉树 + 递归】
java·算法·leetcode·面试·二叉树·递归
Flerken1011 小时前
力扣【SQL连续问题】
数据库·sql·算法·leetcode·数据分析
AomanHao1 小时前
【阅读笔记】基于FPGA的红外图像二阶牛顿插值算法的实现
图像处理·笔记·算法·fpga开发·插值·超分
走在考研路上2 小时前
力扣242.有效的字母异位词
算法·leetcode·职场和发展
sjsjs112 小时前
【数据结构-堆】力扣2530. 执行 K 次操作后的最大分数
数据结构·算法·leetcode
yvestine2 小时前
数据挖掘——朴素贝叶斯分类
人工智能·算法·机器学习·分类·数据挖掘·贝叶斯分类
佑我中华2 小时前
C语言程序设计(第5版)习题解答-第4章
c语言·算法·图论
終不似少年遊*2 小时前
数据结构之线性表
数据结构·笔记·python·算法·线性表
yvestine3 小时前
数据挖掘——模型的评价
人工智能·算法·机器学习·数据挖掘·混淆矩阵·模型评价·正确率
deardao3 小时前
【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 3:算法实现
人工智能·深度学习·神经网络·算法·分类·数据挖掘·极限标签分类