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]\$.
My introduction of algorithm:
I worked on the algorithm several times before, and then also studied a few of "merge intervals" questions on this site, found a sibling question - Finding the total time elapsed in the union of time intervals. The two problems are very similar, my working solution for Leetcode \$56\$ is also \$O(nlogn)\$ time by first sorting the input interval start time, then do a linear scan of the sorted array.
I spent more than one hour to practice again and passed all test cases through leetcode online judge, but I tried three times. First time I forgot to add edge case, after the for
loop, Leetcode online judge showed me that the test case with one interval only failed, and then, I did not use sorted intervals in the code and then failed test cases with two intervals \$[1,4]\$,\$[0,4]\$ by returning \$[1,4]\$. Through practice, I added those two test cases in the code as well to remind me the importance of those two bases cases.
Also, I took more than five minutes to look up C# Comparator and then decided to use LINQ to sort the intervals, with a quick study of a Stack Overflow post. I'm still trying to figure out quickest way to sort in a C# implementation.
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MergeIntervals { class Program { /** * Definition for an interval. */ public class Interval { public int start; public int end; public Interval() { start = 0; end = 0; } public Interval(int s, int e) { start = s; end = e; } } static void Main(string[] args) { RunSampleTestcase1(); RunSampleTestcase2(); } /* * Test case: * help to test intervals should be sorted first before merging. * [1,4], [0,4] should not be [1,4] */ public static void RunSampleTestcase1() { IList<Interval> intervals = new List<Interval>(); intervals.Add(new Interval(1, 4)); intervals.Add(new Interval(0, 4)); IList<Interval> nonoverlapped = Merge(intervals); Debug.Assert(nonoverlapped[0].start == 0 && nonoverlapped[0].end == 4); } /* * Test case: * help to test that edge case is handled properly . * [1,4] should be [1,4], not [] * In other words, there is one interval in the input, the result should be itself. * For loop */ public static void RunSampleTestcase2() { IList<Interval> intervals = new List<Interval>(); intervals.Add(new Interval(1, 4)); IList<Interval> nonoverlapped = Merge(intervals); Debug.Assert(nonoverlapped.Count == 1); } /* * Merge all overlapping intervals * Output: all intervals are non-overlapped. * * Use LINQ to sort the intervals - * http://stackoverflow.com/questions/15486/sorting-an-ilist-in-c-sharp */ public static IList<Interval> Merge(IList<Interval> intervals) { IList<Interval> nonOverlapped = new List<Interval>(); if(intervals == null || intervals.Count == 0) { return nonOverlapped; } IEnumerable<Interval> sortedEnumerable = intervals.OrderBy(f => f.start); IList<Interval> sortedIntervals = sortedEnumerable.ToList(); Interval previous = sortedIntervals[0]; for (int i = 1; i < sortedIntervals.Count; i++) { Interval current = sortedIntervals[i]; /* Two intervals are not overlapped */ if(previous.end < current.start) { nonOverlapped.Add(previous); previous = current; continue; } /* merge two overlapped intervals, previous interval's start is smaller than current's start */ previous = new Interval(previous.start, Math.Max(previous.end, current.end)); } // edge case nonOverlapped.Add(previous); return nonOverlapped; } } }