mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-07 17:56:02 +08:00
Add Merge Intervals algorithm (#5516)
This commit is contained in:
@ -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)
|
||||
@ -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)
|
||||
@ -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)
|
||||
@ -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)
|
||||
@ -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)
|
||||
@ -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)
|
||||
@ -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)
|
||||
|
@ -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()][]);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user