题目:
Given a collection of intervals, merge all overlapping intervals.
For example,
Given [1,3],[2,6],[8,10],[15,18]
,
return [1,6],[8,10],[15,18]
.
先把start和end全提出来,分别保存在两个数组中,并对这两个数组进行排序,排序能重新整合各个区间,并且保证了上一个区间的end小于下个区间的end,这是非常重要的一点,将简化了后续的判断。用一个List泛型集合来保存最后筛选结果。首先对start进行遍历,即对所有区间进行遍历,判断下个区间的start是否大于当前区间的end,若大于则证明没有包含关系,否则证明有包含关系,然后对下两个区间进行同样的判断,为了保证合并后区间的start不变,特用到变量j来保证区间start的正确性,只有当不存在包含关系,才执行j++操作。另外同时要注意到i是否为最后一项,若为最后一项直接跳出判断,保存区间。
Java版本:
/**
* Definition for an interval.
* public class Interval {
* int start;
* int end;
* Interval() { start = 0; end = 0; }
* Interval(int s, int e) { start = s; end = e; }
* }
*/
class Solution {
public List<Interval> merge(List<Interval> intervals) {
//先分离start 和 end
int n = intervals.size();
int[] starts = new int[n];
int[] ends = new int[n];
for(int i = 0; i < n; i++){
starts[i] = intervals.get(i).start;
ends[i] = intervals.get(i).end;
}
Arrays.sort(ends);
Arrays.sort(starts);
List<Interval> res = new ArrayList<Interval>();
//对start进行遍历,j用来固定区间的start,
//然后判断下一个区间的start是否大于前一个区间的end,同时对i是否为最后项进行判断
//大于的话,说明没包含关系,则直接返回start[j],end[i]
//否则证明有包含关系,i++,下两个区间进行比较
//简单理解就是i保存最终结果的end,j用来保存最终结果的start
for(int i = 0, j = 0; i < n; i++){
if(i == n - 1 || starts[i + 1] > ends[i]){
res.add(new Interval(starts[j], ends[i]));
j = i + 1;
}
}
return res;
}
}
Python版本:
# Definition for an interval.
# class Interval:
# def __init__(self, s=0, e=0):
# self.start = s
# self.end = e
# class Solution:
# def merge(self, intervals):
# """
# :type intervals: List[Interval]
# :rtype: List[Interval]
# """
# out = []
# for i in sorted(intervals, key=lambda i: i.start):
# if out and i.start <= out[-1].end:
# out[-1].end = max(out[-1].end, i.end)
# else:
# out += i,
# return out
class Solution(object):
def merge(self, intervals):
"""
:type intervals: List[Interval]
:rtype: List[Interval]
"""
if len(intervals) == 0: return []
intervals = sorted(intervals, key = lambda x: x.start)
res = [intervals[0]]
for n in intervals[1:]:
if n.start <= res[-1].end: res[-1].end = max(n.end, res[-1].end)
else: res.append(n)
return res
此处用到了lambda表达式,先将intervals里面所有区间的start进行排序,已保证所有区间内的start是从小到大排序的(注意Java版本是将start和end都进行了排序,所以后面合并区间时就不用对end取最大值操作),并当,前一个区间end大于下个区间的start时,证明有合并区间,取两合并区间end的最大值,作为新区间的end,接着下个interval进行判断。
C++版本:
/**
* Definition for an interval.
* struct Interval {
* int start;
* int end;
* Interval() : start(0), end(0) {}
* Interval(int s, int e) : start(s), end(e) {}
* };
*/
class Solution {
public:
vector<Interval> merge(vector<Interval>& ins) {
if (ins.empty()) return vector<Interval>{};
vector<Interval> res;
sort(ins.begin(), ins.end(), [](Interval a, Interval b){return a.start < b.start;});
res.push_back(ins[0]);
for (int i = 1; i < ins.size(); i++) {
if (res.back().end < ins[i].start) res.push_back(ins[i]);
else
res.back().end = max(res.back().end, ins[i].end);
}
return res;
}
};
思路同Python版本