Skip to content

Commit cdb6412

Browse files
authored
refactor: LineSweep (#5398)
1 parent 6edc009 commit cdb6412

File tree

2 files changed

+56
-42
lines changed

2 files changed

+56
-42
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,62 @@
11
package com.thealgorithms.others;
2+
23
import java.util.Arrays;
34
import java.util.Comparator;
45

5-
/* Line Sweep algorithm can be used to solve range problems by first sorting the list of ranges
6-
* by the start value of the range in non-decreasing order and doing a "sweep" through the number
7-
* line(x-axis) by incrementing the start point by 1 and decrementing the end point+1 by 1 on the
8-
* number line.
9-
* An overlapping range is defined as (StartA <= EndB) AND (EndA >= StartB)
10-
* References
11-
* https://en.wikipedia.org/wiki/Sweep_line_algorithm
12-
* https://en.wikipedia.org/wiki/De_Morgan%27s_laws>
6+
/**
7+
* The Line Sweep algorithm is used to solve range problems efficiently. It works by:
8+
* 1. Sorting a list of ranges by their start values in non-decreasing order.
9+
* 2. Sweeping through the number line (x-axis) while updating a count for each point based on the ranges.
10+
*
11+
* An overlapping range is defined as:
12+
* - (StartA <= EndB) AND (EndA >= StartB)
13+
*
14+
* References:
15+
* - https://en.wikipedia.org/wiki/Sweep_line_algorithm
16+
* - https://en.wikipedia.org/wiki/De_Morgan%27s_laws
1317
*/
1418
public final class LineSweep {
1519
private LineSweep() {
1620
}
1721

1822
/**
19-
* Find Maximum end point
20-
* param = ranges : Array of range[start,end]
21-
* return Maximum Endpoint
23+
* Finds the maximum endpoint from a list of ranges.
24+
*
25+
* @param ranges a 2D array where each element is a range represented by [start, end]
26+
* @return the maximum endpoint among all ranges
2227
*/
2328
public static int findMaximumEndPoint(int[][] ranges) {
24-
Arrays.sort(ranges, Comparator.comparingInt(a -> a[1]));
29+
Arrays.sort(ranges, Comparator.comparingInt(range -> range[1]));
2530
return ranges[ranges.length - 1][1];
2631
}
2732

2833
/**
29-
* Find if any ranges overlap
30-
* param = ranges : Array of range[start,end]
31-
* return true if overlap exists false otherwise.
34+
* Determines if any of the given ranges overlap.
35+
*
36+
* @param ranges a 2D array where each element is a range represented by [start, end]
37+
* @return true if any ranges overlap, false otherwise
3238
*/
3339
public static boolean isOverlap(int[][] ranges) {
40+
if (ranges == null || ranges.length == 0) {
41+
return false;
42+
}
3443

3544
int maximumEndPoint = findMaximumEndPoint(ranges);
36-
Arrays.sort(ranges, Comparator.comparingInt(a -> a[0]));
3745
int[] numberLine = new int[maximumEndPoint + 2];
3846
for (int[] range : ranges) {
39-
4047
int start = range[0];
4148
int end = range[1];
4249

4350
numberLine[start] += 1;
4451
numberLine[end + 1] -= 1;
4552
}
4653

47-
int current = 0;
48-
int overlaps = 0;
49-
for (int num : numberLine) {
50-
current += num;
51-
overlaps = Math.max(overlaps, current);
54+
int currentCount = 0;
55+
int maxOverlaps = 0;
56+
for (int count : numberLine) {
57+
currentCount += count;
58+
maxOverlaps = Math.max(maxOverlaps, currentCount);
5259
}
53-
return overlaps > 1;
60+
return maxOverlaps > 1;
5461
}
5562
}
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
11
package com.thealgorithms.others;
2+
23
import static org.junit.jupiter.api.Assertions.assertEquals;
3-
import static org.junit.jupiter.api.Assertions.assertFalse;
4-
import static org.junit.jupiter.api.Assertions.assertTrue;
54

6-
import org.junit.jupiter.api.Test;
5+
import java.util.stream.Stream;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.Arguments;
8+
import org.junit.jupiter.params.provider.MethodSource;
9+
710
public class LineSweepTest {
11+
private record OverlapTestCase(int[][] ranges, boolean expected) {
12+
}
813

9-
@Test
10-
void testForOverlap() {
11-
int[][] arr = {{0, 10}, {7, 20}, {15, 24}};
12-
assertTrue(LineSweep.isOverlap(arr));
14+
private record MaximumEndPointTestCase(int[][] ranges, int expected) {
1315
}
1416

15-
@Test
16-
void testForNoOverlap() {
17-
int[][] arr = {{0, 10}, {11, 20}, {21, 24}};
18-
assertFalse(LineSweep.isOverlap(arr));
17+
@ParameterizedTest
18+
@MethodSource("provideOverlapTestData")
19+
void testIsOverlap(OverlapTestCase testCase) {
20+
assertEquals(testCase.expected(), LineSweep.isOverlap(testCase.ranges()));
1921
}
20-
@Test
21-
void testForOverlapWhenEndAEqualsStartBAndViceVersa() {
22-
int[][] arr = {{0, 10}, {10, 20}, {21, 24}};
23-
assertTrue(LineSweep.isOverlap(arr));
22+
23+
private static Stream<Arguments> provideOverlapTestData() {
24+
return Stream.of(Arguments.of(new OverlapTestCase(new int[][] {{0, 10}, {7, 20}, {15, 24}}, true)), Arguments.of(new OverlapTestCase(new int[][] {{0, 10}, {11, 20}, {21, 24}}, false)), Arguments.of(new OverlapTestCase(new int[][] {{0, 10}, {10, 20}, {21, 24}}, true)),
25+
Arguments.of(new OverlapTestCase(new int[][] {{5, 10}}, false)), Arguments.of(new OverlapTestCase(new int[][] {{1, 5}, {1, 5}, {1, 5}}, true)), Arguments.of(new OverlapTestCase(new int[][] {{1, 1}, {2, 2}, {3, 3}}, false)), Arguments.of(new OverlapTestCase(new int[][] {}, false)));
2426
}
25-
@Test
26-
void testForMaximumEndPoint() {
27-
int[][] arr = {{10, 20}, {1, 100}, {14, 16}, {1, 8}};
28-
assertEquals(100, LineSweep.findMaximumEndPoint(arr));
27+
28+
@ParameterizedTest
29+
@MethodSource("provideMaximumEndPointTestData")
30+
void testFindMaximumEndPoint(MaximumEndPointTestCase testCase) {
31+
assertEquals(testCase.expected(), LineSweep.findMaximumEndPoint(testCase.ranges()));
32+
}
33+
34+
private static Stream<Arguments> provideMaximumEndPointTestData() {
35+
return Stream.of(Arguments.of(new MaximumEndPointTestCase(new int[][] {{10, 20}, {1, 100}, {14, 16}, {1, 8}}, 100)));
2936
}
3037
}

0 commit comments

Comments
 (0)