Add Merge Intervals algorithm (#5516)

This commit is contained in:
Hardik Pawar
2024-10-03 12:37:44 +05:30
committed by GitHub
parent ea0ed23961
commit ce6d98f8da
3 changed files with 143 additions and 1 deletions

View File

@ -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()][]);
}
}

View File

@ -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);
}
}