Skip to content

Add Merge Intervals algorithm #5516

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
* [SearchSinglyLinkedListRecursion](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/lists/SearchSinglyLinkedListRecursion.java)
* [SinglyLinkedList](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/lists/SinglyLinkedList.java)
* [SkipList](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/lists/SkipList.java)
* [SortedLinkedList](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/lists/SortedLinkedList.java)
* [Node](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/Node.java)
* queues
* [CircularQueue](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/datastructures/queues/CircularQueue.java)
Expand Down Expand Up @@ -268,6 +269,7 @@
* [FractionalKnapsack](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/FractionalKnapsack.java)
* [GaleShapley](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/GaleShapley.java)
* [JobSequencing](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/JobSequencing.java)
* [MergeIntervals](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/MergeIntervals.java)
* [MinimizingLateness](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/greedyalgorithms/MinimizingLateness.java)
* io
* [BufferedReader](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/io/BufferedReader.java)
Expand Down Expand Up @@ -451,6 +453,8 @@
* [TowerOfHanoi](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/TowerOfHanoi.java)
* [TwoPointers](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/TwoPointers.java)
* [Verhoeff](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/others/Verhoeff.java)
* Recursion
* [GenerateSubsets](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/Recursion/GenerateSubsets.java)
* scheduling
* [FCFSScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/FCFSScheduling.java)
* [PreemptivePriorityScheduling](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/scheduling/PreemptivePriorityScheduling.java)
Expand Down Expand Up @@ -500,7 +504,6 @@
* [CombSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CombSort.java)
* [CountingSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CountingSort.java)
* [CycleSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CycleSort.java)
* [DNFSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DNFSort.java)
* [DualPivotQuickSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DualPivotQuickSort.java)
* [DutchNationalFlagSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DutchNationalFlagSort.java)
* [ExchangeSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/ExchangeSort.java)
Expand Down Expand Up @@ -685,6 +688,7 @@
* [RotateSinglyLinkedListsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/RotateSinglyLinkedListsTest.java)
* [SinglyLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/SinglyLinkedListTest.java)
* [SkipListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/SkipListTest.java)
* [SortedLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/SortedLinkedListTest.java)
* queues
* [CircularQueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/CircularQueueTest.java)
* [DequeTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/queues/DequeTest.java)
Expand Down Expand Up @@ -754,6 +758,7 @@
* [FractionalKnapsackTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/FractionalKnapsackTest.java)
* [GaleShapleyTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/GaleShapleyTest.java)
* [JobSequencingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/JobSequencingTest.java)
* [MergeIntervalsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/MergeIntervalsTest.java)
* [MinimizingLatenessTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/greedyalgorithms/MinimizingLatenessTest.java)
* io
* [BufferedReaderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/io/BufferedReaderTest.java)
Expand Down Expand Up @@ -893,6 +898,8 @@
* [TestPrintMatrixInSpiralOrder](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TestPrintMatrixInSpiralOrder.java)
* [TwoPointersTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/TwoPointersTest.java)
* [WorstFitCPUTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/others/WorstFitCPUTest.java)
* Recursion
* [GenerateSubsetsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/Recursion/GenerateSubsetsTest.java)
* scheduling
* [FCFSSchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/FCFSSchedulingTest.java)
* [PreemptivePrioritySchedulingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/scheduling/PreemptivePrioritySchedulingTest.java)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.thealgorithms.greedyalgorithms;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* Problem Statement:
* Given an array of intervals where intervals[i] = [starti, endi].
*
* Merge all overlapping intervals and return an array of the non-overlapping
* intervals
* that cover all the intervals in the input.
*/
public final class MergeIntervals {

/**
* Private constructor to prevent instantiation of this utility class.
*/
private MergeIntervals() {
}

/**
* Merges overlapping intervals from the given array of intervals.
*
* The method sorts the intervals by their start time, then iterates through the
* sorted intervals
* and merges overlapping intervals. If an interval overlaps with the last
* merged interval,
* it updates the end time of the last merged interval. Otherwise, it adds the
* interval as a new entry.
*
* @param intervals A 2D array representing intervals where each element is an
* interval [starti, endi].
* @return A 2D array of merged intervals where no intervals overlap.
*
* Example:
* Input: {{1, 3}, {2, 6}, {8, 10}, {15, 18}}
* Output: {{1, 6}, {8, 10}, {15, 18}}
*/
public static int[][] merge(int[][] intervals) {
// Sort the intervals by their start time (ascending order)
Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));

// List to store merged intervals
List<int[]> merged = new ArrayList<>();

for (int[] interval : intervals) { // Each interval
// If the merged list is empty or the current interval does not overlap with
// the last merged interval, add it to the merged list.
if (merged.isEmpty() || interval[0] > merged.get(merged.size() - 1)[1]) {
merged.add(interval);
} else {
// If there is an overlap, merge the intervals by updating the end time
// of the last merged interval to the maximum end time between the two
// intervals.
merged.get(merged.size() - 1)[1] = Math.max(merged.get(merged.size() - 1)[1], interval[1]);
}
}

// Convert the list of merged intervals back to a 2D array and return it
return merged.toArray(new int[merged.size()][]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.thealgorithms.greedyalgorithms;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;

import org.junit.jupiter.api.Test;

public class MergeIntervalsTest {

@Test
public void testMergeIntervalsWithOverlappingIntervals() {
// Test case where some intervals overlap and should be merged
int[][] intervals = {{1, 3}, {2, 6}, {8, 10}, {15, 18}};
int[][] expected = {{1, 6}, {8, 10}, {15, 18}};
int[][] result = MergeIntervals.merge(intervals);
assertArrayEquals(expected, result);
}

@Test
public void testMergeIntervalsWithNoOverlap() {
// Test case where intervals do not overlap
int[][] intervals = {{1, 2}, {3, 4}, {5, 6}};
int[][] expected = {{1, 2}, {3, 4}, {5, 6}};
int[][] result = MergeIntervals.merge(intervals);
assertArrayEquals(expected, result);
}

@Test
public void testMergeIntervalsWithCompleteOverlap() {
// Test case where intervals completely overlap
int[][] intervals = {{1, 5}, {2, 4}, {3, 6}};
int[][] expected = {{1, 6}};
int[][] result = MergeIntervals.merge(intervals);
assertArrayEquals(expected, result);
}

@Test
public void testMergeIntervalsWithSingleInterval() {
// Test case where only one interval is given
int[][] intervals = {{1, 2}};
int[][] expected = {{1, 2}};
int[][] result = MergeIntervals.merge(intervals);
assertArrayEquals(expected, result);
}

@Test
public void testMergeIntervalsWithEmptyArray() {
// Test case where the input array is empty
int[][] intervals = {};
int[][] expected = {};
int[][] result = MergeIntervals.merge(intervals);
assertArrayEquals(expected, result);
}

@Test
public void testMergeIntervalsWithIdenticalIntervals() {
// Test case where multiple identical intervals are given
int[][] intervals = {{1, 3}, {1, 3}, {1, 3}};
int[][] expected = {{1, 3}};
int[][] result = MergeIntervals.merge(intervals);
assertArrayEquals(expected, result);
}

@Test
public void testMergeIntervalsWithRandomIntervals() {
// Test case with a mix of overlapping and non-overlapping intervals
int[][] intervals = {{1, 4}, {5, 7}, {2, 6}, {8, 10}};
int[][] expected = {{1, 7}, {8, 10}};
int[][] result = MergeIntervals.merge(intervals);
assertArrayEquals(expected, result);
}
}