# LeetCode – Merge Intervals

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

Analysis

The key to solve this problem is defining a Comparator first to sort the arraylist of Intevals.

Java Solution

```public List<Interval> merge(List<Interval> intervals) { List<Interval> result = new ArrayList<Interval>();   if(intervals==null||intervals.size()==0) return result;   Collections.sort(intervals, new Comparator<Interval>(){ public int compare(Interval i1, Interval i2){ if(i1.start!=i2.start) return i1.start-i2.start; else return i1.end-i2.end; } });   Interval pre = intervals.get(0); for(int i=0; i<intervals.size(); i++){ Interval curr = intervals.get(i); if(curr.start>pre.end){ result.add(pre); pre = curr; }else{ Interval merged = new Interval(pre.start, Math.max(pre.end, curr.end)); pre = merged; } } result.add(pre);   return result; }```
Category >> Algorithms
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
```<pre><code>
String foo = "bar";
</code></pre>
```
• Ashwin Rayaprolu

This would be one of the best solution as i merge while performing sort operation. So no additional sort required. Let me know if any one has any better solution

/**
* 1. For the original DataNode2 we need to make sure we merge nodes when ever we see overlap
*
* @author Ashwin Rayaprolu
*
*/
public class MergeInsertIntervals {

/**
* @param args
*/
public static void main(String[] args) {
int[][] originalIntervals = { { 94230, 94299 }, { 94289, 94699 }, { 94200, 94240 }, { 94133, 94133 } };
// Sort our array based on lower bound number
//O(n log n) operation
for(int[] data:originalIntervals){
}

System.out.println(“———Sorted?merged Intervals———-“);
int[][] sortedIntervals = linkedList.traverse();

System.out.println(“———Merged Intervals———-“);

}

}

/**
* @author Ashwin Rayaprolu
*
*/
DataNode2 firstNode;
DataNode2 lastNode;

int size = 0;
// O(log n) operation
void insert(DataNode2 newNode) {
if (firstNode == null) {
firstNode = newNode;
lastNode = newNode;
return;
}

// Keep interval on left if lower bound is < than tempPointer
DataNode2 tempPointer = firstNode;

if (newNode.data[0] < tempPointer.data[0]) {
while (tempPointer.leftPointer != null && newNode.data[0] =tempPointer.data[0]){
//tempPointer.data[1]=
tempPointer.data[0] = newNode.data[0];
return;
}

newNode.rightPointer = tempPointer;

if (tempPointer.leftPointer == null) {
firstNode = newNode;
}

tempPointer.leftPointer = newNode;
++size;

} else {
while (tempPointer.rightPointer != null && newNode.data[0] >= tempPointer.data[0]) {
tempPointer = tempPointer.rightPointer;
}

//If new node is overlapping then merge with current node and return
if(tempPointer.data[1]>=newNode.data[0]){
//tempPointer.data[1]=
tempPointer.data[1] = newNode.data[1];
return;
}

newNode.leftPointer = tempPointer;

if (tempPointer.rightPointer == null) {
lastNode = newNode;
}

tempPointer.rightPointer = newNode;
++size;

}

}

int[][] traverse() {
DataNode2 tempPointer = firstNode;
int[][] sortedArray = new int[size + 1][2];
int index = 0;
while (tempPointer != null) {
sortedArray[index] = tempPointer.data;
++index;
System.out.println(“{” + tempPointer.data[0] + “,” + tempPointer.data[1] + “}”);
tempPointer = tempPointer.rightPointer;
}
return sortedArray;
}
}

/**
* Data Node used for sorting
*
* @author Ashwin Rayaprolu
*
*/
class DataNode2 {
int[] data = {};
DataNode2 leftPointer;
DataNode2 rightPointer;

public DataNode2(int[] data) {
this.data = data;
}

}

• Matias SM

Just a comment (for extra points in an interview and to improve the proposed solution). The proposed comparator implementation:
``` public int compare(Interval i1, Interval i2) { return i1.start - i2.start; } ```

is discouraged since nowhere it is said that start must be positive and that logic may cause under/overflow.

It is better to use Integer.compare (https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#compare(int,%20int))

• Matias SM

This is a guaranteed Time complexity O(N log S) where N is the length of the input and S is the number of different starting (interval) values. It requires O(S) space though.

I think it can be optimized to O(S log S) if we use a hashMap for sToInt and an additional TreeSet (or min heap) to have the starting values ordered increasingly. The space complexity would remain the same (with a higher constant factor).

``` class Interval { final int s; final int e;```

``` Interval(int s, int e) { this.s = s; this.e = e; } /** Assumes there exists an overlap */ Interval merge(Interval o) { return new Interval(Math.min(s, o.s), Math.max(e, o.e)); } } Collection merge(List intervals) { Map sToInt = new TreeMap(); for (Interval i : intervals) { Interval prev = sToInt.put(i.s, i); if (prev != null) { //same start as i, can merge sToInt.put(i.s, i.merge(prev)); } } //Merge intervals if (sToInt.size() <= 1) sToInt.values(); //nothing to merge List result = new ArrayList(); Interval prev = null; for (Interval i : sToInt.values()) { //iterate (sorted by s) if (prev != null && i.s <= prev.e) { prev = prev.merge(i); } else { if (prev != null) result.add(prev); prev = i; } } ```

``` if (prev != null) result.add(prev); return result; } ```

• Ankit Shah

Dear Author of this solution, the above code certainly works and thanks for giving the solution, I took liberty to enhance your code which will print and work for the following output as well: Basically the idea is in the second test case if there are more than one merging intervals, you will need to remove the last element from the result and add a new one.

—————————————————–
Input: [[8,10], [1,3], [2,6], [15,18]]
sorted list: [[1,3], [2,6], [8,10], [15,18]]
merged interval: [[1,6], [8,10], [15,18]]
—————————————————–
Input: [[8,10], [1,3], [2,6], [3,9], [15,18]]
sorted list: [[1,3], [2,6], [3,9], [8,10], [15,18]]
merged interval: [[1,10], [15,18]]
—————————————————–

``` import java.util.*; class Interval { int lo; int hi; Interval() { lo = 0; hi = 0; } Interval(int lo, int hi) { this.lo = lo; this.hi = hi; } @Override public String toString() { return "[" + lo + "," + hi + "]"; } } public class MergeIntervals { public static ArrayList merge(ArrayList list) { Collections.sort(list, new Comparator() { public int compare(Interval i1, Interval i2) { if (i1.lo == i2.lo) { return i1.hi - i2.hi; } return i1.lo - i2.lo; } }); System.out.println("Sorted Input: " + list); ArrayList result = new ArrayList(); Interval prev = list.get(0); for (int i = 1; i = current.lo) { Interval interval = new Interval(prev.lo, Math.max(prev.hi, current.hi)); prev = interval; } else { prev = current; } removeIfExist(result, prev); result.add(prev); } return result; } private static void removeIfExist(ArrayList result, Interval prev) { if (result.size() > 0) { Interval existing = result.get(result.size() - 1); if (existing.lo == prev.lo) { result.remove(result.size() - 1); } } } public static void main(String[] args) { ArrayList list = new ArrayList(); list.add(new Interval(8, 10)); list.add(new Interval(1, 3)); list.add(new Interval(2, 6)); list.add(new Interval(15, 18)); System.out.println("Input: " + list); System.out.println("merged interval: " + merge(list)); System.out.println("-----------------------------------------------------"); list = new ArrayList(); list.add(new Interval(8, 10)); list.add(new Interval(1, 3)); list.add(new Interval(2, 6)); list.add(new Interval(3, 9)); list.add(new Interval(15, 18)); System.out.println("Input: " + list); System.out.println("merged interval: " + merge(list)); System.out.println("-----------------------------------------------------"); } } ```

• Omar Edgardo Lugo Sánchez

my solution, im the same lol

ArrayList input = new ArrayList();

ArrayList r = new ArrayList();

//Given [1,3],[2,6],[8,10],[15,18],

Collections.sort(input);

// compare items

for(int i=0;i=obj2.I){

obj2.I = obj1.I; // merge invertals

}else{

r.add(obj1); // could not be merged so add to Result

}

}

// add last item