面试经典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
  • -231 <= nums[i] <= 231 - 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] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。

提示:

  • 1 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 104

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] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

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

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

提示:

  • 1 <= points.length <= 105
  • points[i].length == 2
  • -231 <= xstart < xend <= 231 - 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. 之后合并区间,不过取的是当前区间与维护区间的并集。如果没有并集就开枪,否则更新维护区间为两者的并集。
相关推荐
这就是编程几秒前
自回归模型的新浪潮?GPT-4o图像生成技术解析与未来展望
人工智能·算法·机器学习·数据挖掘·回归
羑悻的小杀马特3 分钟前
【狂热算法篇】探寻图论幽径:Bellman - Ford 算法的浪漫征程(通俗易懂版)
c++·算法·图论·bellman_ford算法
Fantasydg4 小时前
DAY 31 leetcode 142--链表.环形链表
算法·leetcode·链表
basketball6164 小时前
C++ STL常用算法之常用排序算法
c++·算法·排序算法
qystca4 小时前
蓝桥云客 岛屿个数
算法·dfs·bfs
什码情况5 小时前
回文时间 - 携程机试真题题解
数据结构·python·算法·华为od·机试
lwewan6 小时前
26考研——栈、队列和数组_数组和特殊矩阵(3)
数据结构·笔记·考研·算法
拾零吖6 小时前
枚举算法-day2
数据结构·算法·leetcode
已经成为了代码的形状6 小时前
关于交换并查集内元素的一些题的做法
数据结构·算法
self-discipline6346 小时前
【Java】Java核心知识点与相应面试技巧(七)——类与对象(二)
java·开发语言·面试