Merge Intervals

来源:互联网 发布:智能停车场收费软件 编辑:程序博客网 时间:2024/05/22 07:58

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].

解法一:从头开始进行两两合并

/** * 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 Interval implements Comparable<Interval>{int start;int end;Interval() { start = 0; end = 0; }Interval(int s, int e) { start = s; end = e; }public int compareTo(Interval o){return this.start - o.start;}}public class Solution {    public static List<Interval> merge(List<Interval> intervals){Collections.sort(intervals);List<Interval> result = new ArrayList<Interval>();        int length = intervals.size();        if(length <= 1)        return intervals;        Interval first = intervals.get(0),second = new Interval();        for(int i = 1; i < length; i++)        {        second = intervals.get(i);        if(second.start > first.end)        {        result.add(first);        first = second;        }        else         {        first.end = Math.max(first.end, second.end);}        }        //最后一次合并        result.add(first);        return result;    }}

解法二:

区间合并 和 求最长区间 一样,关键在于如何记录区间信息,能够降低复杂度。


最简单的思路是用一个bool数组,记录区间中的每一位是否被覆盖。

例如:

intervals: [1, 4] [8, 9] [20, 30] [7, 14] [2, 9]

设一个数组 bool f[30],初始化全部为false

[1, 4]就把f[1]..f[4]全部置为true

其他区间一次类推,最后扫描f数组,就能得到区间合并的结果。

这种做法对于小数据还行,大数据会超市。


这样做,存在很多重复工作,例如[1, 4] [8, 9] [7, 14] [2, 9]这四个区间,会反复将f[2] f[3] f[4][ f[5] f[6] f[7] f[8] f[9]设为true。

所以,我们需要考虑的是如何去除重复的工作。实际上,两个端点就能描述出一个区间,关键在于如何标记出两个端点,让我们在扫描时能够知道这个区间被覆盖。


一个很巧妙的做法就是进入一个区间就加1,出一个区间就减1,如果数值大于0,说明当前处于一个区间中。

还是以刚刚的intervals为例。

设数组 int l[30], r[30],初始化全部为0 

[1, 4]:l[1]++, r[4]--

[8, 9]:l[8]++, r[9]--

...

扫描时,用一个count记录,每次:

count += l[i],如果count>0说明i处于一个区间中

count -= r[i],如果count==0说明i是一个区间的尾端点

public static List<Interval> merge(List<Interval> intervals) {        List<Interval> result = new ArrayList<Interval>();        int length = intervals.size();        if(length <= 1)        return intervals;        int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;        for(int i = 0;i < length; i++)        {        Interval tmp = intervals.get(i);        max = Math.max(max, tmp.end);        min = Math.min(min, tmp.start);        }        int[] left = new int[max + 1];        int[] right = new int[max + 1];        for(int i = 0;i < length; i++)        {        Interval tmp = intervals.get(i);        left[tmp.start]++;        right[tmp.end]--;        }        int start = -1, count = 0;        for(int i = min; i <= max; i++)        {        count += left[i];        if(count > 0 && start == -1)        start = i;        count += right[i];        if(count == 0 && start != -1)        {        result.add(new Interval(start, i));        start = -1;        }        }        return result;    }



 

0 0
原创粉丝点击