What do you understand by efficient? Fast? Least memory usage? Mantainable code?
There are tons of ways you could solve this, some of them can entail seemingly a lot of code but maybe thats not bad. For example, consider the following approach:
public struct Interval<T> where T: IComparable<T>
{
public T LowerBound { get; }
public T UpperBound { get; }
public Interval(T lowerBound, T upperBound)
{
Debug.Assert(upperBound.CompareTo(lowerBound) > 0);
LowerBound = lowerBound;
UpperBound = upperBound;
}
public static bool AreOverlapping(Interval<T> first, Interval<T> second) =>
first.UpperBound.CompareTo(second.LowerBound) > 0 &&
second.UpperBound.CompareTo(first.LowerBound) > 0;
public static Interval<T> Union(Interval<T> first, Interval<T> second)
{
Debug.Assert(AreOverlapping(first, second));
return new Interval<T>(Min(first.LowerBound, second.LowerBound),
Max(first.UpperBound, second.UpperBound));
}
public override string ToString() => $"[{LowerBound}, {UpperBound}]";
private static T Min(T t1, T t2)
{
if (t1.CompareTo(t2) <= 0)
return t1;
return t2;
}
private static T Max(T t1, T t2)
{
if (t1.CompareTo(t2) >= 0)
return t1;
return t2;
}
}
And now, our method to extract non-overlapping intervals would be:
public static IEnumerable<Interval<T>> GetOverlappingIntervals<T>(this IEnumerable<Interval<T>> intervals)
where T : IComparable<T>
{
var stack = new Stack<Interval<T>>();
foreach (var interval in intervals.OrderBy(i => i.LowerBound))
{
if (stack.Count == 0)
{
stack.Push(interval);
}
else
{
var previous = stack.Peek();
if (Interval<T>.AreOverlapping(interval, previous))
{
stack.Pop();
stack.Push(Interval<T>.Union(interval, previous));
}
else
{
stack.Push(interval);
}
}
}
return stack;
}
Note that this solution will not perform the union of adjacent intervals, not sure if this is what you want.
Is this solution mantainable? Yes, the code is pretty much self explanatory. Is it the most efficient? Well, probably not, but who cares if its "efficient" enough and it meets your performance goals. If it doesn't, then do start optimizing it.