Skip to content

Commit 75aac0a

Browse files
committed
Add Merge Intervals algorithm
1 parent 0bd86b3 commit 75aac0a

File tree

2 files changed

+135
-0
lines changed

2 files changed

+135
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.thealgorithms.greedyalgorithms;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
/**
8+
* Problem Statement:
9+
* Given an array of intervals where intervals[i] = [starti, endi].
10+
*
11+
* Merge all overlapping intervals and return an array of the non-overlapping
12+
* intervals
13+
* that cover all the intervals in the input.
14+
*/
15+
public final class MergeIntervals {
16+
17+
/**
18+
* Private constructor to prevent instantiation of this utility class.
19+
*/
20+
private MergeIntervals() {
21+
}
22+
23+
/**
24+
* Merges overlapping intervals from the given array of intervals.
25+
*
26+
* The method sorts the intervals by their start time, then iterates through the
27+
* sorted intervals
28+
* and merges overlapping intervals. If an interval overlaps with the last
29+
* merged interval,
30+
* it updates the end time of the last merged interval. Otherwise, it adds the
31+
* interval as a new entry.
32+
*
33+
* @param intervals A 2D array representing intervals where each element is an
34+
* interval [starti, endi].
35+
* @return A 2D array of merged intervals where no intervals overlap.
36+
*
37+
* Example:
38+
* Input: {{1, 3}, {2, 6}, {8, 10}, {15, 18}}
39+
* Output: {{1, 6}, {8, 10}, {15, 18}}
40+
*/
41+
public static int[][] merge(int[][] intervals) {
42+
// Sort the intervals by their start time (ascending order)
43+
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));
44+
45+
// List to store merged intervals
46+
List<int[]> merged = new ArrayList<>();
47+
48+
for (int[] interval : intervals) { // Each interval
49+
// If the merged list is empty or the current interval does not overlap with
50+
// the last merged interval, add it to the merged list.
51+
if (merged.isEmpty() || interval[0] > merged.get(merged.size() - 1)[1]) {
52+
merged.add(interval);
53+
} else {
54+
// If there is an overlap, merge the intervals by updating the end time
55+
// of the last merged interval to the maximum end time between the two
56+
// intervals.
57+
merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], interval[1]);
58+
}
59+
}
60+
61+
// Convert the list of merged intervals back to a 2D array and return it
62+
return merged.toArray(new int[merged.size()][]);
63+
}
64+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.thealgorithms.greedyalgorithms;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
5+
import org.junit.jupiter.api.Test;
6+
7+
public class MergeIntervalsTest {
8+
9+
@Test
10+
public void testMergeIntervalsWithOverlappingIntervals() {
11+
// Test case where some intervals overlap and should be merged
12+
int[][] intervals = { { 1, 3 }, { 2, 6 }, { 8, 10 }, { 15, 18 } };
13+
int[][] expected = { { 1, 6 }, { 8, 10 }, { 15, 18 } };
14+
int[][] result = MergeIntervals.merge(intervals);
15+
assertArrayEquals(expected, result);
16+
}
17+
18+
@Test
19+
public void testMergeIntervalsWithNoOverlap() {
20+
// Test case where intervals do not overlap
21+
int[][] intervals = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
22+
int[][] expected = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
23+
int[][] result = MergeIntervals.merge(intervals);
24+
assertArrayEquals(expected, result);
25+
}
26+
27+
@Test
28+
public void testMergeIntervalsWithCompleteOverlap() {
29+
// Test case where intervals completely overlap
30+
int[][] intervals = { { 1, 5 }, { 2, 4 }, { 3, 6 } };
31+
int[][] expected = { { 1, 6 } };
32+
int[][] result = MergeIntervals.merge(intervals);
33+
assertArrayEquals(expected, result);
34+
}
35+
36+
@Test
37+
public void testMergeIntervalsWithSingleInterval() {
38+
// Test case where only one interval is given
39+
int[][] intervals = { { 1, 2 } };
40+
int[][] expected = { { 1, 2 } };
41+
int[][] result = MergeIntervals.merge(intervals);
42+
assertArrayEquals(expected, result);
43+
}
44+
45+
@Test
46+
public void testMergeIntervalsWithEmptyArray() {
47+
// Test case where the input array is empty
48+
int[][] intervals = {};
49+
int[][] expected = {};
50+
int[][] result = MergeIntervals.merge(intervals);
51+
assertArrayEquals(expected, result);
52+
}
53+
54+
@Test
55+
public void testMergeIntervalsWithIdenticalIntervals() {
56+
// Test case where multiple identical intervals are given
57+
int[][] intervals = { { 1, 3 }, { 1, 3 }, { 1, 3 } };
58+
int[][] expected = { { 1, 3 } };
59+
int[][] result = MergeIntervals.merge(intervals);
60+
assertArrayEquals(expected, result);
61+
}
62+
63+
@Test
64+
public void testMergeIntervalsWithRandomIntervals() {
65+
// Test case with a mix of overlapping and non-overlapping intervals
66+
int[][] intervals = { { 1, 4 }, { 5, 7 }, { 2, 6 }, { 8, 10 } };
67+
int[][] expected = { { 1, 6 }, { 5, 7 }, { 8, 10 } };
68+
int[][] result = MergeIntervals.merge(intervals);
69+
assertArrayEquals(expected, result);
70+
}
71+
}

0 commit comments

Comments
 (0)