Skip to content

Commit ce6d98f

Browse files
authored
Add Merge Intervals algorithm (#5516)
1 parent ea0ed23 commit ce6d98f

File tree

3 files changed

+143
-1
lines changed

3 files changed

+143
-1
lines changed

DIRECTORY.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@
156156
* [SearchSinglyLinkedListRecursion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/lists/SearchSinglyLinkedListRecursion.java)
157157
* [SinglyLinkedList](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java)
158158
* [SkipList](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/lists/SkipList.java)
159+
* [SortedLinkedList](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/lists/SortedLinkedList.java)
159160
* [Node](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/Node.java)
160161
* queues
161162
* [CircularQueue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/CircularQueue.java)
@@ -268,6 +269,7 @@
268269
* [FractionalKnapsack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java)
269270
* [GaleShapley](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/GaleShapley.java)
270271
* [JobSequencing](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java)
272+
* [MergeIntervals](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/MergeIntervals.java)
271273
* [MinimizingLateness](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/MinimizingLateness.java)
272274
* io
273275
* [BufferedReader](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/io/BufferedReader.java)
@@ -451,6 +453,8 @@
451453
* [TowerOfHanoi](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/TowerOfHanoi.java)
452454
* [TwoPointers](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/TwoPointers.java)
453455
* [Verhoeff](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/Verhoeff.java)
456+
* Recursion
457+
* [GenerateSubsets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/Recursion/GenerateSubsets.java)
454458
* scheduling
455459
* [FCFSScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/FCFSScheduling.java)
456460
* [PreemptivePriorityScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java)
@@ -500,7 +504,6 @@
500504
* [CombSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CombSort.java)
501505
* [CountingSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CountingSort.java)
502506
* [CycleSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CycleSort.java)
503-
* [DNFSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DNFSort.java)
504507
* [DualPivotQuickSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DualPivotQuickSort.java)
505508
* [DutchNationalFlagSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DutchNationalFlagSort.java)
506509
* [ExchangeSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/ExchangeSort.java)
@@ -685,6 +688,7 @@
685688
* [RotateSinglyLinkedListsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedListsTest.java)
686689
* [SinglyLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java)
687690
* [SkipListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/SkipListTest.java)
691+
* [SortedLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/SortedLinkedListTest.java)
688692
* queues
689693
* [CircularQueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/CircularQueueTest.java)
690694
* [DequeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java)
@@ -754,6 +758,7 @@
754758
* [FractionalKnapsackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackTest.java)
755759
* [GaleShapleyTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/GaleShapleyTest.java)
756760
* [JobSequencingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingTest.java)
761+
* [MergeIntervalsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/MergeIntervalsTest.java)
757762
* [MinimizingLatenessTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessTest.java)
758763
* io
759764
* [BufferedReaderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/io/BufferedReaderTest.java)
@@ -893,6 +898,8 @@
893898
* [TestPrintMatrixInSpiralOrder](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java)
894899
* [TwoPointersTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TwoPointersTest.java)
895900
* [WorstFitCPUTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/WorstFitCPUTest.java)
901+
* Recursion
902+
* [GenerateSubsetsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/Recursion/GenerateSubsetsTest.java)
896903
* scheduling
897904
* [FCFSSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/FCFSSchedulingTest.java)
898905
* [PreemptivePrioritySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java)
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+
}
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, 7}, {8, 10}};
68+
int[][] result = MergeIntervals.merge(intervals);
69+
assertArrayEquals(expected, result);
70+
}
71+
}

0 commit comments

Comments
 (0)