From da9a80f5cc2be2f816fd91ab7a24d8a612fdf0fc Mon Sep 17 00:00:00 2001 From: alxkm Date: Mon, 26 Aug 2024 00:35:35 +0200 Subject: [PATCH 1/2] refactor: LineSweep --- .../com/thealgorithms/others/LineSweep.java | 53 +++++++++++-------- .../thealgorithms/others/LineSweepTest.java | 44 ++++++++------- 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/thealgorithms/others/LineSweep.java b/src/main/java/com/thealgorithms/others/LineSweep.java index 946ba6edb475..b7db964c98d0 100644 --- a/src/main/java/com/thealgorithms/others/LineSweep.java +++ b/src/main/java/com/thealgorithms/others/LineSweep.java @@ -1,42 +1,49 @@ package com.thealgorithms.others; + import java.util.Arrays; import java.util.Comparator; -/* Line Sweep algorithm can be used to solve range problems by first sorting the list of ranges - * by the start value of the range in non-decreasing order and doing a "sweep" through the number - * line(x-axis) by incrementing the start point by 1 and decrementing the end point+1 by 1 on the - * number line. - * An overlapping range is defined as (StartA <= EndB) AND (EndA >= StartB) - * References - * https://en.wikipedia.org/wiki/Sweep_line_algorithm - * https://en.wikipedia.org/wiki/De_Morgan%27s_laws> +/** + * The Line Sweep algorithm is used to solve range problems efficiently. It works by: + * 1. Sorting a list of ranges by their start values in non-decreasing order. + * 2. Sweeping through the number line (x-axis) while updating a count for each point based on the ranges. + * + * An overlapping range is defined as: + * - (StartA <= EndB) AND (EndA >= StartB) + * + * References: + * - https://en.wikipedia.org/wiki/Sweep_line_algorithm + * - https://en.wikipedia.org/wiki/De_Morgan%27s_laws */ public final class LineSweep { private LineSweep() { } /** - * Find Maximum end point - * param = ranges : Array of range[start,end] - * return Maximum Endpoint + * Finds the maximum endpoint from a list of ranges. + * + * @param ranges a 2D array where each element is a range represented by [start, end] + * @return the maximum endpoint among all ranges */ public static int findMaximumEndPoint(int[][] ranges) { - Arrays.sort(ranges, Comparator.comparingInt(a -> a[1])); + Arrays.sort(ranges, Comparator.comparingInt(range -> range[1])); return ranges[ranges.length - 1][1]; } /** - * Find if any ranges overlap - * param = ranges : Array of range[start,end] - * return true if overlap exists false otherwise. + * Determines if any of the given ranges overlap. + * + * @param ranges a 2D array where each element is a range represented by [start, end] + * @return true if any ranges overlap, false otherwise */ public static boolean isOverlap(int[][] ranges) { + if (ranges == null || ranges.length == 0) { + return false; + } int maximumEndPoint = findMaximumEndPoint(ranges); - Arrays.sort(ranges, Comparator.comparingInt(a -> a[0])); int[] numberLine = new int[maximumEndPoint + 2]; for (int[] range : ranges) { - int start = range[0]; int end = range[1]; @@ -44,12 +51,12 @@ public static boolean isOverlap(int[][] ranges) { numberLine[end + 1] -= 1; } - int current = 0; - int overlaps = 0; - for (int num : numberLine) { - current += num; - overlaps = Math.max(overlaps, current); + int currentCount = 0; + int maxOverlaps = 0; + for (int count : numberLine) { + currentCount += count; + maxOverlaps = Math.max(maxOverlaps, currentCount); } - return overlaps > 1; + return maxOverlaps > 1; } } diff --git a/src/test/java/com/thealgorithms/others/LineSweepTest.java b/src/test/java/com/thealgorithms/others/LineSweepTest.java index 6bf6ef5b3002..1482b2204c2b 100644 --- a/src/test/java/com/thealgorithms/others/LineSweepTest.java +++ b/src/test/java/com/thealgorithms/others/LineSweepTest.java @@ -1,30 +1,36 @@ package com.thealgorithms.others; + import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + public class LineSweepTest { + private record OverlapTestCase(int[][] ranges, boolean expected) { + } - @Test - void testForOverlap() { - int[][] arr = {{0, 10}, {7, 20}, {15, 24}}; - assertTrue(LineSweep.isOverlap(arr)); + private record MaximumEndPointTestCase(int[][] ranges, int expected) { } - @Test - void testForNoOverlap() { - int[][] arr = {{0, 10}, {11, 20}, {21, 24}}; - assertFalse(LineSweep.isOverlap(arr)); + @ParameterizedTest + @MethodSource("provideOverlapTestData") + void testIsOverlap(OverlapTestCase testCase) { + assertEquals(testCase.expected(), LineSweep.isOverlap(testCase.ranges())); } - @Test - void testForOverlapWhenEndAEqualsStartBAndViceVersa() { - int[][] arr = {{0, 10}, {10, 20}, {21, 24}}; - assertTrue(LineSweep.isOverlap(arr)); + + private static Stream provideOverlapTestData() { + 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)), 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))); } - @Test - void testForMaximumEndPoint() { - int[][] arr = {{10, 20}, {1, 100}, {14, 16}, {1, 8}}; - assertEquals(100, LineSweep.findMaximumEndPoint(arr)); + + @ParameterizedTest + @MethodSource("provideMaximumEndPointTestData") + void testFindMaximumEndPoint(MaximumEndPointTestCase testCase) { + assertEquals(testCase.expected(), LineSweep.findMaximumEndPoint(testCase.ranges())); + } + + private static Stream provideMaximumEndPointTestData() { + return Stream.of(Arguments.of(new MaximumEndPointTestCase(new int[][]{{10, 20}, {1, 100}, {14, 16}, {1, 8}}, 100))); } } From d93c1e8702b492be71cd6f6c6a41086419ffaaa9 Mon Sep 17 00:00:00 2001 From: alxkm Date: Mon, 26 Aug 2024 00:38:47 +0200 Subject: [PATCH 2/2] checkstyle: fix formatting --- src/test/java/com/thealgorithms/others/LineSweepTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/thealgorithms/others/LineSweepTest.java b/src/test/java/com/thealgorithms/others/LineSweepTest.java index 1482b2204c2b..59fd0fafb068 100644 --- a/src/test/java/com/thealgorithms/others/LineSweepTest.java +++ b/src/test/java/com/thealgorithms/others/LineSweepTest.java @@ -21,7 +21,8 @@ void testIsOverlap(OverlapTestCase testCase) { } private static Stream provideOverlapTestData() { - 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)), 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))); + 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)), + 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))); } @ParameterizedTest @@ -31,6 +32,6 @@ void testFindMaximumEndPoint(MaximumEndPointTestCase testCase) { } private static Stream provideMaximumEndPointTestData() { - return Stream.of(Arguments.of(new MaximumEndPointTestCase(new int[][]{{10, 20}, {1, 100}, {14, 16}, {1, 8}}, 100))); + return Stream.of(Arguments.of(new MaximumEndPointTestCase(new int[][] {{10, 20}, {1, 100}, {14, 16}, {1, 8}}, 100))); } }