今天的力扣打卡题是 57. 插入区间 ,我们再顺便练习两道类似的简单区间题目,比如:判断区间是否重叠(252. 会议室)、56. 合并区间。这类面试题目还挺讨巧的,因为不需要掌握什么数据结构与算法的先验知识,看懂题目之后模拟一遍即可,很容易考察出应聘者到底会不会写代码。
一、判断区间是否重叠
题目描述
力扣 252. 会议室
难度:Easy给定一个会议时间安排的数组 intervals ,每个会议时间都会包括开始和结束的时间
intervals[i] = [starti, endi] , 请你判断一个人是否能够参加这里面的 全部会议。示例 1::
输入: intervals = [[0,30],[5,10],[15,20]]
输出: false
解释:存在重叠区间,一个人在同一时刻只能参加一个会议。
示例 2::
输入: intervals = [[7,10],[2,4]]
输出: true
解释: 不存在重叠区间
思路分析
因为一个人在同一时刻只能参加一个会议,因此题目实质是判断是否存在重叠区间,这个简单,将区间按照会议开始时间进行排序,然后遍历一遍判断即可。
代码实现
func canAttendMeetings(temp [][]int)bool{
//将区间按照会议的开始顺序进行排序
sort.Slice(temp, func(i, j int) bool {
return temp[i][0]<temp[j][0]
})
falg:=true
//遍历会议,如果下一个会议在前一个会议之前就结束了,返回false
for i:=0;i<len(temp);i++{
if i>0&&temp[i][0]<temp[i-1][1]{
return false
}
}
return falg
}
**
二、合并区间
题目描述
力扣 56. 合并区间
难度:Medium给出一个区间的集合,请合并所有重叠的区间。
示例 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] 可被视为重叠区间。
思路分析
和上一题一样,首先对区间按照起始端点进行升序排序,然后逐个判断当前区间是否与前一个区间重叠,如果不重叠的话将当前区间直接加入结果集,反之如果重叠的话,就将当前区间与前一个区间进行合并。
代码实现
func merged(intervals [][]int) [][]int {
//定义结果集
res:=[][]int{}
//先把区间按照起始位置升序排序
sort.Slice(intervals, func(i, j int) bool {
return intervals[i][0]<intervals[j][0]
})
res=append(res,intervals[0])//先把第一个区间直接加入到结果集
//遍历区间
for i:=1;i<len(intervals);i++{
//如果当前区间的起始位置>结果集最后一个区间的最终位置,说明不重叠,直接把当前区间加入到结果集
if intervals[i][0]>res[len(res)-1][1]{
res=append(res,intervals[i])
}else{
//反之说明重叠,把当前区间合并到结果集的最后一个区间
res[len(res)-1][1]=maxx(res[len(res)-1][1],intervals[i][1])
}
}
return res
}
//比较大小
func maxx(x,y int)int {
if x>=y{
return x
}else{
return y
}
}
三、插入区间
题目描述
57.插入区间
难度:Medium给出一个无重叠的 ,按照区间起始端点排序的区间列表。
在列表中插入一个新的区间,你需要确保列表中的区间仍然 有序且不重叠(如果有必要的话,可以 合并区间)。
示例 1::
输入: intervals = [[1,3],[6,9]], newInterval = [2,5]
输出: [[1,5],[6,9]]
解释: 新区间[2,5] 与 [1,3]重叠,因此合并成为 [1,5]。示例 2::
输入: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval= [4,8]
输出: [[1,2],[3,10],[12,16]]
解释: 新区间 [4,8] 与 [3,5],[6,7],[8,10] 重叠,因此合并成为 [3,10]。
思路分析
本题中的区间已经按照起始端点升序排列,因此我们直接遍历区间列表,寻找新区间的插入位置即可。具体步骤如下:
- 首先将新区间左边且相离的区间加入结果集(遍历时,如果当前区间的结束位置小于新区间的开始位置,说明当前区间在新区间的左边且相离);
- 接着判断当前区间是否与新区间重叠,重叠的话就进行合并,直到遍历到当前区间在新区间的右边且相离,将最终合并后的新区间加入结果集;
- 最后将新区间右边且相离的区间加入结果集。
代码实现
func insert(intervals [][]int, newInterval []int) [][]int {
//结果集
res := [][]int{}
if len(intervals) == 0 {
res = append(res, newInterval)
return res
}
i:=0
//遍历区间
for ;i<len(intervals);i++{
//如果当前区间的结束位置小于插入区间的开始位置,那么可以直接加入结果集
if intervals[i][1]<newInterval[0]{
res=append(res,intervals[i])
}else{
break
}
}
//遍历集合,对插入区间进行合并
for ;i<len(intervals);i++{
//如果当前区间的起始位置小于插入区间的结束位置,考虑合并
if intervals[i][0]<=newInterval[1]{
newInterval[0]=min(intervals[i][0],newInterval[0])
newInterval[1]=max(intervals[i][1],newInterval[1])
}else{
//否则退出,将剩余的区间直接添加到结果集
break
}
}
res=append(res,newInterval)//把合并后的区间加入到结果集
for ;i<len(intervals);i++{//剩余区间都是大于插入区间的,可以直接加入到结果集
res=append(res,intervals[i])
}
return res
}
func max(x,y int)int {
if x>y{
return x
}else{
return y
}
}
func min(x,y int)int{
if x<y{
return x
}else{
return y
}
}