区间问题

所谓区间问题,就是线段问题,让你合并所有线段找出线段的交集等等。主要有两个技巧:

  1. 排序。常见的排序方法就是按照区间起点排序,或者先按照起点升序排序,若起点相同,则按照终点降序排序。当然,如果你非要按照终点排序,无非对称操作,本质都是一样的。
  2. 画图就是说不要偷懒,勤动手,两个区间的相对位置到底有几种可能,不同的相对位置我们的代码应该怎么去处理。

区间覆盖问题

Leetcode 1288 删除被覆盖区间

题目问我们,去除被覆盖区间之后,还剩下多少区间,那么我们可以先算一算,被覆盖区间有多少个,然后和总数相减就是剩余区间数。

对于这种区间问题,如果没啥头绪,首先排个序看看,比如我们按照区间的起点进行升序排序:

排序之后,两个相邻区间可能有如下三种相对位置:

对于上面三种情况,我们应该进行如下处理:

  1. 情况一,找到了覆盖区间。
  2. 情况二,两个区间可以合并,成一个大区间。
  3. 情况三,两个区间完全不相交。

根据上面几种情况,我们可以写出如下代码:

int removeCoveredIntervals(int[][] intvs) {// 按照起点升序排列,起点相同时降序排列Arrays.sort(intvs, (a, b) -> {if (a[0] == b[0]) {return b[1] - a[1];}return a[0] - b[0]; });// 记录合并区间的起点和终点int left = intvs[0][0];int right = intvs[0][1];int res = 0;for (int i = 1; i < intvs.length; i++) {int[] intv = intvs[i];// 情况一,找到覆盖区间if (left <= intv[0] && right >= intv[1]) {res++;}// 情况二,找到相交区间,合并if (right >= intv[0] && right <= intv[1]) {right = intv[1];}// 情况三,完全不相交,更新起点和终点if (right < intv[0]) {left = intv[0];right = intv[1];}}return intvs.length - res;
}

上面是本题的解法代码, 起点升序排列,终点降序排列的目的是防止如下情况的发生

对于这两个起点相同的区间,我们需要保证长的那个区间在上面(按照终点降序),这样才会被判定为覆盖,否则会被错误地判定为相交,少算一个覆盖区间。

关于java当中二维数组的一些操作


// java创建一个二维数组
int[][] arr = {{1, 4}, {3, 6}, {2, 8}};
System.out.println(Arrays.toString(data)); // 使用这个方法可以打印出这个二维数组里面的每一个数组到底是什么
System.out.println(arr.length); // 3
int[] arr1 = arr[1];
System.out.println(arr1[0]); // arr1本身是一个地址值,但是通过取值里面的具体元素,可以得到的是数组里面的具体值

java当中的lambda函数

lambda函数表达式主要有四个例子

*   - 1、不需要参数,返回值为5 () -> 5
*   - 2、接收一个参数(数字类型),返回其2倍的值
*   - 3、接收2个参数(数字),并返回他们的差值 (x, y) -> x – y
*   - 4、接收2个int型整数,返回他们的和  (int x, int y) -> x + y
*   - 5、接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) (String s) -> System.out.print(s)

区间合并问题

Leetcode 56题,合并区间

解决区间问题的一般思路是先排序,然后观察规律。

一个区间可以表示为**[start, end]**,前文聊的区间调度问题,需要按end排序,以便满足贪心选择性质。而对于区间合并问题,其实按end和start排序都可以,不过为了清晰起见,我们选择按start排序。


显然,对于几个相交区间合并后的结果区间x,x.start一定是这些相交区间中start最小的,x.end一定是这些相交区间中end最大的

由于已经排了序,x.start很好确定,求x.end也很容易,可以类比在数组中找最大值的过程:

int max_ele = arr[0];
for (int i = 1; i < arr.length; i++) max_ele = max(max_ele, arr[i]);
return max_ele;

完整代码 python

# intervals 形如 [[1,3],[2,6]...]
def merge(intervals):if not intervals: return []# 按区间的 start 升序排列intervals.sort(key=lambda intv: intv[0])res = []res.append(intervals[0])for i in range(1, len(intervals)):curr = intervals[i]# res 中最后一个元素的引用last = res[-1]if curr[0] <= last[1]:# 找到最大的 endlast[1] = max(last[1], curr[1])else:# 处理下一个待合并区间res.append(curr)return res

java版本

class Solution {public int[][] merge(int[][] intervals) {LinkedList<int[]> res = new LinkedList<>();// 按区间的 start 升序排列Arrays.sort(intervals, (a, b) -> {return a[0] - b[0];});res.add(intervals[0]);for (int i = 1; i < intervals.length; i++) {int[] curr = intervals[i];// res 中最后一个元素的引用int[] last = res.getLast();if (curr[0] <= last[1]) {last[1] = Math.max(last[1], curr[1]);} else {// 处理下一个待合并区间res.add(curr);}}// return res.toArray(new int[0][0]);return res.toArray(new int[res.size()][];}
}

toArray() 将一个集合转换为一个数组

区间交集问题

区间列表交集

题目很好理解,就是让你找交集,注意区间都是闭区间

解决区间问题的思路一般先排序,以便操作,不过题目说已经排好序了,那么可以用两个索引指针在A和B中游走,把交集找出来,

代码大概是这样的:

# A, B 形如 [[0,2],[5,10]...]
def intervalIntersection(A, B):i, j = 0, 0res = []while i < len(A) and j < len(B):# ...j += 1i += 1return res

不难,我们先老老实实分析一下各种情况。

首先,对于两个区间,我们用[a1,a2]和[b1,b2]表示在A和B中的两个区间,那么什么情况下这两个区间没有交集呢

只有这两种情况,写成代码的条件是:

if b2 < a1 or a2 < b1:[a1,a2] 和 [b1,b2] 无交集

那么,什么情况下,两个区间存在交集呢?根据命题的否定,上面逻辑的否命题就是存在交集的条件:

这很简单吧,就这四种情况**而已。那么接下来思考,这几种情况下,交集是否有什么共同点呢?

我们惊奇地发现,交集区间是有规律的! **如果交集区间是[c1,c2],那么c1=max(a1,b1),c2=min(a2,b2)!**这一点就是寻找交集的核心,我们把代码更进一步:

while i < len(A) and j < len(B):a1, a2 = A[i][0], A[i][1]b1, b2 = B[j][0], B[j][1]if b2 >= a1 and a2 >= b1:res.append([max(a1, b1), min(a2, b2)])# ...

最后一步,我们的指针i和j肯定要前进(递增)的,什么时候应该前进呢?


结合动画示例就很好理解了,是否前进,只取决于a2和b2的大小关系:

while i < len(A) and j < len(B):# ...if b2 < a2:j += 1else:i += 1

综上所述,代码实现

Python代码实现

# A, B 形如 [[0,2],[5,10]...]
def intervalIntersection(A, B):i, j = 0, 0 # 双指针res = []while i < len(A) and j < len(B):a1, a2 = A[i][0], A[i][1]b1, b2 = B[j][0], B[j][1]# 两个区间存在交集if b2 >= a1 and a2 >= b1:# 计算出交集,加入 resres.append([max(a1, b1), min(a2, b2)])# 指针前进if b2 < a2: j += 1else:       i += 1return res

Java代码实现

class Solution {public int[][] intervalIntersection(int[][] A, int[][] B) {List<int[]> res = new LinkedList<>();int i = 0, j = 0;while (i < A.length && j < B.length) {int a1 = A[i][0], a2 = A[i][1];int b1 = B[j][0], b2 = B[j][1];if (b2 >= a1 && a2 >= b1) {res.add(new int[]{Math.max(a1, b1), Math.min(a2, b2)});}if (b2 < a2) {j++;} else {i++;}}return res.toArray(new int[0][0]);}
}

总结:

  • 区间类问题看起来都比较复杂,情况很多难以处理,但实际上通过观察各种不同情况之间的共性可以发现规律,用简洁的代码就能处理。

秒杀所有区间相关问题相关推荐

  1. 区间相关问题的学习: 最多不相交区间问题,区间选点问题与区间覆盖问题

    区间相关问题包括: 1)最多不相交区间问题; 2)区间选点问题; 3)区间覆盖问题等. 最多不相交区间问题(又叫选择不相交区间,最大不相交覆盖等等),是指数轴上有n个开区间(a,b),选择尽量多个区间 ...

  2. 全局内存BSS,DATA,RODATA的区别以及其他内存区间相关

    刚接触c语言的时候,了解了全局变量这个概念,只知道所谓全局变量的意思就是代码文件里面所有的函数都可以随时调用修改的变量,而其实这种理解是十分不准确的,但随着后期学习的深入,接触了计算机组成原理和汇编的 ...

  3. 51Nod 1091 线段的重叠(贪心+区间相关,板子题)

    1091 线段的重叠 基准时间限制:1 秒 空间限制:131072 KB 分值: 5         难度:1级算法题 X轴上有N条线段,每条线段包括1个起点和终点.线段的重叠是这样来算的,[10 2 ...

  4. Leetcode刷题986. 区间列表的交集

    给定两个由一些 闭区间 组成的列表,每个区间列表都是成对不相交的,并且已经排序. 返回这两个区间列表的交集. (形式上,闭区间 [a, b](其中 a <= b)表示实数 x 的集合,而 a & ...

  5. 如何使用alexa_如何使用Alexa来帮助您入睡

    如何使用alexa Having trouble dozing off? Your Amazon Echo or Alexa-enabled device can play sounds, music ...

  6. 东哥手把手带你刷二叉树|第三期

    学算法认准 labuladong 后台回复进群一起力扣???? 读完本文,你可以去力扣解决: 652.寻找重复子树(Medium) 接前文 手把手带你刷二叉树(第一期)和 手把手带你刷二叉树(第二期) ...

  7. 秒杀多线程第十一篇 读者写者问题

    与上一篇<秒杀多线程第十篇 生产者消费者问题>的生产者消费者问题一样,读者写者也是一个非常著名的同步问题.读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文 ...

  8. 数组的合并和升序排列_区间调度问题之区间合并

    读完本文,你可以去力扣拿下如下题目: 56.合并区间 ----------- 上篇文章用贪心算法解决了区间调度问题:给你很多区间,让你求其中的最大不重叠子集. 其实对于区间相关的问题,还有很多其他类型 ...

  9. 【20210827】【系统设计】“秒杀系统”架构设计分析

    时间:2021年08月27日 作者:小蒋聊技术 大家好,欢迎来到小蒋聊技术.小蒋准备和大家一起聊聊技术的那些事. 在互联网高速发展的今天,大家已经习惯了一个又一个的便捷互联网服务在改变着我们的生活.出 ...

最新文章

  1. 2021年大数据Kafka(十二):❤️Kafka配额限速机制❤️
  2. TYVJ 2002 扑克牌 题解
  3. 微信小程序websocket聊天室
  4. delphi的接口support_学习到的关于Delphi的接口
  5. 垃圾收集器与内存分配策略(五)之垃圾日志与常见参数
  6. 干货|机器学习零基础?不要怕,吴恩达机器学习课程笔记2-多元线性回归
  7. 实验3 | 由遍历序列构造二叉树
  8. 登录注册HTML页面代码
  9. 该模型是内置式的MTPA控制,速度环的输出为给定转矩,然后方式1通过求解MTPA方程得到dq给定电流
  10. ZigBee-CC2530单片机 - 按键控制LED
  11. Python 全栈打造某宝客微信机器人
  12. 2016年年终总结--勿忘初心
  13. java实现图片压缩
  14. OpenHarmony LiteOS C-SKY指令集移植指北
  15. Proteus仿真——用74LS194设计一个8个灯的流水灯电路
  16. 蚂蚁客服介绍-微服网络
  17. endnote打开后闪退_为什么微信打不开闪退怎么回事?微信打不开怎么修复?
  18. go-swagger简单使用
  19. 配置数据库ODBC数据源
  20. Android各种沉浸式状态栏实现

热门文章

  1. 本地ie打开html布局乱,网页设计:浏览器在兼容模式下布局全乱了 – 解决办法...
  2. [js] 网易漫画爬虫
  3. 华为交换机PVID与VLAN ID及TAG 、UNTAG学习记录
  4. 新南威尔士大学COMP9021 QUIZ1课业解析
  5. 计算机无法使用网络连接到服务器,电脑无法连接网络并诊断提示DNS服务器未响应的解决方法...
  6. 51la流量获取链接
  7. L4W4作业2 深度学习与艺术 - 神经风格迁移
  8. B2B网站排名显示前十名皆出自亚洲
  9. python硬件驱动_从零开始:手把手教你安装深度学习操作系统、驱动和各种python库!...
  10. 在微型计算机中 多媒体信息包括,公务员考试常识题:1、具有多媒体功能的微型计算机系统中,常用的CD-ROM是...