Skip to content

Commit d95cb4f

Browse files
committed
Add MergeIntervals task solution
1 parent 37bdb8a commit d95cb4f

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package by.andd3dfx.common;
2+
3+
import java.util.ArrayList;
4+
import java.util.Comparator;
5+
import java.util.List;
6+
7+
/**
8+
* <pre>
9+
* <a href="https://leetcode.com/problems/merge-intervals/description/">Task description</a>
10+
*
11+
* Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals,
12+
* and return an array of the non-overlapping intervals that cover all the intervals in the input.
13+
*
14+
* Example 1:
15+
* Input: intervals = [[1,3],[2,6],[8,10],[15,18]]
16+
* Output: [[1,6],[8,10],[15,18]]
17+
* Explanation: Since intervals [1,3] and [2,6] overlap, merge them into [1,6].
18+
*
19+
* Example 2:
20+
* Input: intervals = [[1,4],[4,5]]
21+
* Output: [[1,5]]
22+
* Explanation: Intervals [1,4] and [4,5] are considered overlapping.
23+
*
24+
* Example 3:
25+
* Input: intervals = [[4,7],[1,4]]
26+
* Output: [[1,7]]
27+
* Explanation: Intervals [1,4] and [4,7] are considered overlapping.
28+
* </pre>
29+
* <p>
30+
*/
31+
public class MergeIntervals {
32+
33+
public int[][] merge(int[][] intervals) {
34+
List<Point> points = new ArrayList<>();
35+
populatePointList(intervals, points);
36+
points.sort(Comparator.comparing(Point::x)
37+
.thenComparingInt(o -> o.type.ordinal())
38+
);
39+
40+
List<Pair> intersections = determinePairs(points);
41+
42+
int[][] result = new int[intersections.size()][2];
43+
for (int i = 0; i < intersections.size(); i++) {
44+
result[i][0] = intersections.get(i).x1;
45+
result[i][1] = intersections.get(i).x2;
46+
}
47+
return result;
48+
}
49+
50+
private List<Pair> determinePairs(List<Point> points) {
51+
List<Pair> intersections = new ArrayList<>();
52+
var startsAmount = 0;
53+
var x = 0;
54+
for (var point : points) {
55+
switch (point.type) {
56+
case START -> {
57+
startsAmount++;
58+
if (startsAmount == 1) {
59+
x = point.x;
60+
}
61+
}
62+
case END -> {
63+
if (startsAmount <= 0) {
64+
throw new IllegalStateException("END going before any START!");
65+
}
66+
startsAmount--;
67+
if (startsAmount == 0) {
68+
intersections.add(new Pair(x, point.x));
69+
}
70+
}
71+
}
72+
}
73+
return intersections;
74+
}
75+
76+
private void populatePointList(int[][] intervals, List<Point> points) {
77+
for (var pair : intervals) {
78+
points.add(new Point(pair[0], Point.Type.START));
79+
points.add(new Point(pair[1], Point.Type.END));
80+
}
81+
}
82+
83+
public record Point(int x, Type type) {
84+
85+
public enum Type {
86+
START, END
87+
}
88+
}
89+
90+
public record Pair(int x1, int x2) {
91+
92+
}
93+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package by.andd3dfx.common;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import org.junit.Before;
6+
import org.junit.Test;
7+
8+
public class MergeIntervalsTest {
9+
10+
private MergeIntervals mergeIntervals;
11+
12+
@Before
13+
public void setUp() throws Exception {
14+
mergeIntervals = new MergeIntervals();
15+
}
16+
17+
@Test
18+
public void merge() {
19+
assertThat(mergeIntervals.merge(new int[][]{{1, 3}, {2, 6}, {8, 10}, {15, 18}}))
20+
.isEqualTo(new int[][]{{1, 6}, {8, 10}, {15, 18}});
21+
22+
assertThat(mergeIntervals.merge(new int[][]{{1, 4}, {4, 5}}))
23+
.isEqualTo(new int[][]{{1, 5}});
24+
25+
assertThat(mergeIntervals.merge(new int[][]{{4, 7}, {1, 4}}))
26+
.isEqualTo(new int[][]{{1, 7}});
27+
}
28+
}

0 commit comments

Comments
 (0)