From 9bc6bf3812b137e1e0e44aa71946d8f8c7c94a8b Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 5 Oct 2025 13:11:59 +0530 Subject: [PATCH 1/7] refactor: Enhance docs, code, add tests in `SkylineProblem` --- .../thealgorithms/others/SkylineProblem.java | 220 ++++++++++++------ .../others/SkylineProblemTest.java | 131 +++++++---- 2 files changed, 233 insertions(+), 118 deletions(-) diff --git a/src/main/java/com/thealgorithms/others/SkylineProblem.java b/src/main/java/com/thealgorithms/others/SkylineProblem.java index e84a5c5b585b..7a807c072177 100644 --- a/src/main/java/com/thealgorithms/others/SkylineProblem.java +++ b/src/main/java/com/thealgorithms/others/SkylineProblem.java @@ -1,17 +1,45 @@ + package com.thealgorithms.others; import java.util.ArrayList; +import java.util.List; +import java.util.Objects; /** - * The {@code SkylineProblem} class is used to solve the skyline problem using a - * divide-and-conquer approach. - * It reads input for building data, processes it to find the skyline, and - * prints the skyline. + *

Skyline Problem

+ *

+ * Solves the classic skyline problem using a divide-and-conquer approach. Given + * a list of buildings (each defined by left, height, right), + * computes the silhouette (skyline) formed by these buildings when viewed from + * a distance. + *

+ *

+ * Usage example: + * + *

+ * SkylineProblem sp = new SkylineProblem();
+ * sp.building = new SkylineProblem.Building[3];
+ * sp.add(1, 10, 5);
+ * sp.add(2, 15, 7);
+ * sp.add(3, 12, 9);
+ * List skyline = sp.findSkyline(0, 2);
+ * 
+ *

+ *

+ * This class is not thread-safe. + *

*/ public class SkylineProblem { - Building[] building; - int count; + /** + * Array of buildings to process. Must be initialized before use. + */ + public Building[] building; + + /** + * Number of buildings added so far. + */ + public int count; /** * Adds a building with the given left, height, and right values to the @@ -20,8 +48,23 @@ public class SkylineProblem { * @param left The left x-coordinate of the building. * @param height The height of the building. * @param right The right x-coordinate of the building. + * @throws IllegalArgumentException if left >= right or height < 0 + * @throws IllegalStateException if building array is not initialized or is + * full */ public void add(int left, int height, int right) { + if (building == null) { + throw new IllegalStateException("Building array not initialized"); + } + if (count >= building.length) { + throw new IllegalStateException("Building array is full"); + } + if (left >= right) { + throw new IllegalArgumentException("Left coordinate must be less than right coordinate"); + } + if (height < 0) { + throw new IllegalArgumentException("Height must be non-negative"); + } building[count++] = new Building(left, height, right); } @@ -29,92 +72,97 @@ public void add(int left, int height, int right) { * Computes the skyline for a range of buildings using the divide-and-conquer * strategy. * - * @param start The starting index of the buildings to process. - * @param end The ending index of the buildings to process. + * @param start The starting index of the buildings to process (inclusive). + * @param end The ending index of the buildings to process (inclusive). * @return A list of {@link Skyline} objects representing the computed skyline. + * @throws IllegalArgumentException if indices are out of bounds or building + * array is null */ - public ArrayList findSkyline(int start, int end) { + public List findSkyline(int start, int end) { + if (building == null) { + throw new IllegalArgumentException("Building array is not initialized"); + } + if (start < 0 || end >= count || start > end) { + throw new IllegalArgumentException("Invalid start or end index"); + } // Base case: only one building, return its skyline. if (start == end) { - ArrayList list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(new Skyline(building[start].left, building[start].height)); - list.add(new Skyline(building[end].right, 0)); // Add the end of the building + list.add(new Skyline(building[start].right, 0)); // Add the end of the building return list; } int mid = (start + end) / 2; - - ArrayList sky1 = this.findSkyline(start, mid); // Find the skyline of the left half - ArrayList sky2 = this.findSkyline(mid + 1, end); // Find the skyline of the right half + List sky1 = this.findSkyline(start, mid); // Find the skyline of the left half + List sky2 = this.findSkyline(mid + 1, end); // Find the skyline of the right half return this.mergeSkyline(sky1, sky2); // Merge the two skylines } /** * Merges two skylines (sky1 and sky2) into one combined skyline. * - * @param sky1 The first skyline list. - * @param sky2 The second skyline list. + * @param sky1 The first skyline list. Not modified. + * @param sky2 The second skyline list. Not modified. * @return A list of {@link Skyline} objects representing the merged skyline. + * @throws NullPointerException if either argument is null */ - public ArrayList mergeSkyline(ArrayList sky1, ArrayList sky2) { - int currentH1 = 0; - int currentH2 = 0; - ArrayList skyline = new ArrayList<>(); - int maxH = 0; - - // Merge the two skylines - while (!sky1.isEmpty() && !sky2.isEmpty()) { - if (sky1.get(0).coordinates < sky2.get(0).coordinates) { - int currentX = sky1.get(0).coordinates; - currentH1 = sky1.get(0).height; - - if (currentH1 < currentH2) { - sky1.remove(0); - if (maxH != currentH2) { - skyline.add(new Skyline(currentX, currentH2)); - } - } else { - maxH = currentH1; - sky1.remove(0); - skyline.add(new Skyline(currentX, currentH1)); - } - } else { - int currentX = sky2.get(0).coordinates; - currentH2 = sky2.get(0).height; - - if (currentH2 < currentH1) { - sky2.remove(0); - if (maxH != currentH1) { - skyline.add(new Skyline(currentX, currentH1)); - } - } else { - maxH = currentH2; - sky2.remove(0); - skyline.add(new Skyline(currentX, currentH2)); - } + public List mergeSkyline(List sky1, List sky2) { + Objects.requireNonNull(sky1, "sky1 must not be null"); + Objects.requireNonNull(sky2, "sky2 must not be null"); + int i = 0, j = 0; + int h1 = 0, h2 = 0; + int prevHeight = 0; + List result = new ArrayList<>(); + while (i < sky1.size() && j < sky2.size()) { + Skyline p1 = sky1.get(i); + Skyline p2 = sky2.get(j); + int x; + if (p1.coordinates < p2.coordinates) { + x = p1.coordinates; + h1 = p1.height; + i++; + } else if (p2.coordinates < p1.coordinates) { + x = p2.coordinates; + h2 = p2.height; + j++; + } else { // same x + x = p1.coordinates; + h1 = p1.height; + h2 = p2.height; + i++; + j++; + } + int maxH = Math.max(h1, h2); + if (result.isEmpty() || prevHeight != maxH) { + result.add(new Skyline(x, maxH)); + prevHeight = maxH; } } - - // Add any remaining points from sky1 or sky2 - while (!sky1.isEmpty()) { - skyline.add(sky1.get(0)); - sky1.remove(0); + // Append remaining points + while (i < sky1.size()) { + Skyline p = sky1.get(i++); + if (result.isEmpty() || result.get(result.size() - 1).height != p.height || result.get(result.size() - 1).coordinates != p.coordinates) { + result.add(new Skyline(p.coordinates, p.height)); + } } - - while (!sky2.isEmpty()) { - skyline.add(sky2.get(0)); - sky2.remove(0); + while (j < sky2.size()) { + Skyline p = sky2.get(j++); + if (result.isEmpty() || result.get(result.size() - 1).height != p.height || result.get(result.size() - 1).coordinates != p.coordinates) { + result.add(new Skyline(p.coordinates, p.height)); + } } - - return skyline; + return result; } /** - * A class representing a point in the skyline with its x-coordinate and height. + * Represents a point in the skyline with its x-coordinate and height. */ - public class Skyline { - public int coordinates; - public int height; + public static class Skyline { + /** The x-coordinate of the skyline point. */ + public final int coordinates; + /** The height of the skyline at the given coordinate. */ + public final int height; /** * Constructor for the {@code Skyline} class. @@ -126,16 +174,36 @@ public Skyline(int coordinates, int height) { this.coordinates = coordinates; this.height = height; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Skyline skyline = (Skyline) o; + return coordinates == skyline.coordinates && height == skyline.height; + } + + @Override + public int hashCode() { + return Objects.hash(coordinates, height); + } + + @Override + public String toString() { + return "(" + coordinates + ", " + height + ")"; + } } /** - * A class representing a building with its left, height, and right - * x-coordinates. + * Represents a building with its left, height, and right x-coordinates. */ - public class Building { - public int left; - public int height; - public int right; + public static class Building { + /** The left x-coordinate of the building. */ + public final int left; + /** The height of the building. */ + public final int height; + /** The right x-coordinate of the building. */ + public final int right; /** * Constructor for the {@code Building} class. @@ -149,5 +217,11 @@ public Building(int left, int height, int right) { this.height = height; this.right = right; } + + @Override + public String toString() { + return "Building{" + + "left=" + left + ", height=" + height + ", right=" + right + '}'; + } } } diff --git a/src/test/java/com/thealgorithms/others/SkylineProblemTest.java b/src/test/java/com/thealgorithms/others/SkylineProblemTest.java index 1ed5ced709c1..6f5997d9e064 100644 --- a/src/test/java/com/thealgorithms/others/SkylineProblemTest.java +++ b/src/test/java/com/thealgorithms/others/SkylineProblemTest.java @@ -1,86 +1,127 @@ package com.thealgorithms.others; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.*; -import java.util.ArrayList; +import java.util.*; import org.junit.jupiter.api.Test; public class SkylineProblemTest { @Test - public void testSingleBuildingSkyline() { + void testSingleBuildingSkyline() { SkylineProblem skylineProblem = new SkylineProblem(); skylineProblem.building = new SkylineProblem.Building[1]; skylineProblem.add(2, 10, 9); - ArrayList result = skylineProblem.findSkyline(0, 0); + List result = skylineProblem.findSkyline(0, 0); - assertEquals(2, result.get(0).coordinates); - assertEquals(10, result.get(0).height); - assertEquals(9, result.get(1).coordinates); - assertEquals(0, result.get(1).height); + assertEquals(List.of(new SkylineProblem.Skyline(2, 10), new SkylineProblem.Skyline(9, 0)), result); } @Test - public void testTwoBuildingsSkyline() { + void testTwoBuildingsSkyline() { SkylineProblem skylineProblem = new SkylineProblem(); skylineProblem.building = new SkylineProblem.Building[2]; skylineProblem.add(1, 11, 5); skylineProblem.add(2, 6, 7); - ArrayList result = skylineProblem.findSkyline(0, 1); + List result = skylineProblem.findSkyline(0, 1); // Expected skyline points: (1, 11), (5, 6), (7, 0) - assertEquals(1, result.get(0).coordinates); - assertEquals(11, result.get(0).height); - assertEquals(5, result.get(1).coordinates); - assertEquals(6, result.get(1).height); - assertEquals(7, result.get(2).coordinates); - assertEquals(0, result.get(2).height); + assertEquals(List.of(new SkylineProblem.Skyline(1, 11), new SkylineProblem.Skyline(5, 6), new SkylineProblem.Skyline(7, 0)), result); } @Test - public void testMergeSkyline() { + void testMergeSkyline() { + List sky1 = List.of(new SkylineProblem.Skyline(2, 10), new SkylineProblem.Skyline(9, 0)); + List sky2 = List.of(new SkylineProblem.Skyline(3, 15), new SkylineProblem.Skyline(7, 0)); SkylineProblem skylineProblem = new SkylineProblem(); - ArrayList sky1 = new ArrayList<>(); - ArrayList sky2 = new ArrayList<>(); - - sky1.add(skylineProblem.new Skyline(2, 10)); - sky1.add(skylineProblem.new Skyline(9, 0)); - - sky2.add(skylineProblem.new Skyline(3, 15)); - sky2.add(skylineProblem.new Skyline(7, 0)); - - ArrayList result = skylineProblem.mergeSkyline(sky1, sky2); + List result = skylineProblem.mergeSkyline(sky1, sky2); // Expected merged skyline: (2, 10), (3, 15), (7, 10), (9, 0) - assertEquals(2, result.get(0).coordinates); - assertEquals(10, result.get(0).height); - assertEquals(3, result.get(1).coordinates); - assertEquals(15, result.get(1).height); - assertEquals(7, result.get(2).coordinates); - assertEquals(10, result.get(2).height); - assertEquals(9, result.get(3).coordinates); - assertEquals(0, result.get(3).height); + assertEquals(List.of(new SkylineProblem.Skyline(2, 10), new SkylineProblem.Skyline(3, 15), new SkylineProblem.Skyline(7, 10), new SkylineProblem.Skyline(9, 0)), result); } @Test - public void testMultipleBuildingsSkyline() { + void testMultipleBuildingsSkyline() { SkylineProblem skylineProblem = new SkylineProblem(); skylineProblem.building = new SkylineProblem.Building[3]; skylineProblem.add(1, 10, 5); skylineProblem.add(2, 15, 7); skylineProblem.add(3, 12, 9); - ArrayList result = skylineProblem.findSkyline(0, 2); + List result = skylineProblem.findSkyline(0, 2); + + assertEquals(List.of(new SkylineProblem.Skyline(1, 10), new SkylineProblem.Skyline(2, 15), new SkylineProblem.Skyline(7, 12), new SkylineProblem.Skyline(9, 0)), result); + } + + @Test + void testAddBuildingInvalidCases() { + SkylineProblem skylineProblem = new SkylineProblem(); + // Not initialized + Exception ex = assertThrows(IllegalStateException.class, () -> skylineProblem.add(1, 2, 3)); + assertTrue(ex.getMessage().contains("not initialized")); + + skylineProblem.building = new SkylineProblem.Building[1]; + skylineProblem.add(1, 2, 3); + // Array full + Exception ex2 = assertThrows(IllegalStateException.class, () -> skylineProblem.add(4, 5, 6)); + assertTrue(ex2.getMessage().contains("full")); + + // Invalid left >= right + SkylineProblem skylineProblem2 = new SkylineProblem(); + skylineProblem2.building = new SkylineProblem.Building[1]; + Exception ex3 = assertThrows(IllegalArgumentException.class, () -> skylineProblem2.add(5, 2, 2)); + assertTrue(ex3.getMessage().contains("Left coordinate")); + + // Invalid height < 0 + Exception ex4 = assertThrows(IllegalArgumentException.class, () -> skylineProblem2.add(1, -1, 2)); + assertTrue(ex4.getMessage().contains("Height must be non-negative")); + } + + @Test + void testFindSkylineInvalidCases() { + SkylineProblem skylineProblem = new SkylineProblem(); + // Not initialized + Exception ex = assertThrows(IllegalArgumentException.class, () -> skylineProblem.findSkyline(0, 0)); + assertTrue(ex.getMessage().contains("not initialized")); + + skylineProblem.building = new SkylineProblem.Building[2]; + skylineProblem.count = 1; + Exception ex2 = assertThrows(IllegalArgumentException.class, () -> skylineProblem.findSkyline(0, 1)); + assertTrue(ex2.getMessage().contains("Invalid start or end index")); + } + + @Test + void testMergeSkylineNullCases() { + SkylineProblem skylineProblem = new SkylineProblem(); + Exception ex1 = assertThrows(NullPointerException.class, () -> skylineProblem.mergeSkyline(null, List.of())); + Exception ex2 = assertThrows(NullPointerException.class, () -> skylineProblem.mergeSkyline(List.of(), null)); + assertTrue(ex1.getMessage().contains("sky1")); + assertTrue(ex2.getMessage().contains("sky2")); + } + + @Test + void testSkylineEqualsAndHashCode() { + SkylineProblem.Skyline s1 = new SkylineProblem.Skyline(1, 2); + SkylineProblem.Skyline s2 = new SkylineProblem.Skyline(1, 2); + SkylineProblem.Skyline s3 = new SkylineProblem.Skyline(2, 2); + assertEquals(s1, s2); + assertEquals(s1.hashCode(), s2.hashCode()); + assertNotEquals(s1, s3); + assertNotEquals(null, s1); + assertNotEquals("string", s1); + } - assertEquals(1, result.get(0).coordinates); - assertEquals(10, result.get(0).height); - assertEquals(2, result.get(1).coordinates); - assertEquals(15, result.get(1).height); - assertEquals(7, result.get(2).coordinates); - assertEquals(12, result.get(2).height); - assertEquals(9, result.get(3).coordinates); - assertEquals(0, result.get(3).height); + @Test + void testSkylineToString() { + SkylineProblem.Skyline s = new SkylineProblem.Skyline(5, 10); + assertEquals("(5, 10)", s.toString()); + } + + @Test + void testBuildingToString() { + SkylineProblem.Building b = new SkylineProblem.Building(1, 2, 3); + assertEquals("Building{left=1, height=2, right=3}", b.toString()); } } From a2ba20f702467a5bdcc4d83b7328a33715023890 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 5 Oct 2025 13:17:29 +0530 Subject: [PATCH 2/7] Fix lint --- .../thealgorithms/others/SkylineProblem.java | 14 +++++++---- .../others/SkylineProblemTest.java | 23 +++++++++++++++---- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/thealgorithms/others/SkylineProblem.java b/src/main/java/com/thealgorithms/others/SkylineProblem.java index 7a807c072177..1d060be58863 100644 --- a/src/main/java/com/thealgorithms/others/SkylineProblem.java +++ b/src/main/java/com/thealgorithms/others/SkylineProblem.java @@ -110,8 +110,10 @@ public List findSkyline(int start, int end) { public List mergeSkyline(List sky1, List sky2) { Objects.requireNonNull(sky1, "sky1 must not be null"); Objects.requireNonNull(sky2, "sky2 must not be null"); - int i = 0, j = 0; - int h1 = 0, h2 = 0; + int i = 0; + int j = 0; + int h1 = 0; + int h2 = 0; int prevHeight = 0; List result = new ArrayList<>(); while (i < sky1.size() && j < sky2.size()) { @@ -177,8 +179,12 @@ public Skyline(int coordinates, int height) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Skyline skyline = (Skyline) o; return coordinates == skyline.coordinates && height == skyline.height; } diff --git a/src/test/java/com/thealgorithms/others/SkylineProblemTest.java b/src/test/java/com/thealgorithms/others/SkylineProblemTest.java index 6f5997d9e064..fddca17e3892 100644 --- a/src/test/java/com/thealgorithms/others/SkylineProblemTest.java +++ b/src/test/java/com/thealgorithms/others/SkylineProblemTest.java @@ -1,11 +1,14 @@ package com.thealgorithms.others; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.*; +import java.util.List; import org.junit.jupiter.api.Test; -public class SkylineProblemTest { +class SkylineProblemTest { @Test void testSingleBuildingSkyline() { @@ -95,8 +98,18 @@ void testFindSkylineInvalidCases() { @Test void testMergeSkylineNullCases() { SkylineProblem skylineProblem = new SkylineProblem(); - Exception ex1 = assertThrows(NullPointerException.class, () -> skylineProblem.mergeSkyline(null, List.of())); - Exception ex2 = assertThrows(NullPointerException.class, () -> skylineProblem.mergeSkyline(List.of(), null)); + Exception ex1 = assertThrows(NullPointerException.class, new org.junit.jupiter.api.function.Executable() { + @Override + public void execute() { + skylineProblem.mergeSkyline(null, List.of()); + } + }); + Exception ex2 = assertThrows(NullPointerException.class, new org.junit.jupiter.api.function.Executable() { + @Override + public void execute() { + skylineProblem.mergeSkyline(List.of(), null); + } + }); assertTrue(ex1.getMessage().contains("sky1")); assertTrue(ex2.getMessage().contains("sky2")); } From 311158ed62287042b595249576353aa523c67fb7 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 5 Oct 2025 13:25:58 +0530 Subject: [PATCH 3/7] Fix --- .../thealgorithms/others/SkylineProblem.java | 16 +++++++++++- .../others/SkylineProblemTest.java | 26 ++++++------------- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/thealgorithms/others/SkylineProblem.java b/src/main/java/com/thealgorithms/others/SkylineProblem.java index 1d060be58863..470d861664ad 100644 --- a/src/main/java/com/thealgorithms/others/SkylineProblem.java +++ b/src/main/java/com/thealgorithms/others/SkylineProblem.java @@ -34,13 +34,27 @@ public class SkylineProblem { /** * Array of buildings to process. Must be initialized before use. */ - public Building[] building; + private Building[] building; /** * Number of buildings added so far. */ public int count; + /** + * Sets the building array to the specified size. + * + * @param size The size of the building array. + * @throws IllegalArgumentException if size is negative + */ + public void setBuilding(int size) { + if (size < 0) { + throw new IllegalArgumentException("Size must be non-negative"); + } + this.building = new Building[size]; + this.count = 0; + } + /** * Adds a building with the given left, height, and right values to the * buildings list. diff --git a/src/test/java/com/thealgorithms/others/SkylineProblemTest.java b/src/test/java/com/thealgorithms/others/SkylineProblemTest.java index fddca17e3892..3112d769debf 100644 --- a/src/test/java/com/thealgorithms/others/SkylineProblemTest.java +++ b/src/test/java/com/thealgorithms/others/SkylineProblemTest.java @@ -13,7 +13,7 @@ class SkylineProblemTest { @Test void testSingleBuildingSkyline() { SkylineProblem skylineProblem = new SkylineProblem(); - skylineProblem.building = new SkylineProblem.Building[1]; + skylineProblem.setBuilding(1); skylineProblem.add(2, 10, 9); List result = skylineProblem.findSkyline(0, 0); @@ -24,7 +24,7 @@ void testSingleBuildingSkyline() { @Test void testTwoBuildingsSkyline() { SkylineProblem skylineProblem = new SkylineProblem(); - skylineProblem.building = new SkylineProblem.Building[2]; + skylineProblem.setBuilding(2); skylineProblem.add(1, 11, 5); skylineProblem.add(2, 6, 7); @@ -48,7 +48,7 @@ void testMergeSkyline() { @Test void testMultipleBuildingsSkyline() { SkylineProblem skylineProblem = new SkylineProblem(); - skylineProblem.building = new SkylineProblem.Building[3]; + skylineProblem.setBuilding(3); skylineProblem.add(1, 10, 5); skylineProblem.add(2, 15, 7); skylineProblem.add(3, 12, 9); @@ -65,7 +65,7 @@ void testAddBuildingInvalidCases() { Exception ex = assertThrows(IllegalStateException.class, () -> skylineProblem.add(1, 2, 3)); assertTrue(ex.getMessage().contains("not initialized")); - skylineProblem.building = new SkylineProblem.Building[1]; + skylineProblem.setBuilding(1); skylineProblem.add(1, 2, 3); // Array full Exception ex2 = assertThrows(IllegalStateException.class, () -> skylineProblem.add(4, 5, 6)); @@ -73,7 +73,7 @@ void testAddBuildingInvalidCases() { // Invalid left >= right SkylineProblem skylineProblem2 = new SkylineProblem(); - skylineProblem2.building = new SkylineProblem.Building[1]; + skylineProblem2.setBuilding(1); Exception ex3 = assertThrows(IllegalArgumentException.class, () -> skylineProblem2.add(5, 2, 2)); assertTrue(ex3.getMessage().contains("Left coordinate")); @@ -89,7 +89,7 @@ void testFindSkylineInvalidCases() { Exception ex = assertThrows(IllegalArgumentException.class, () -> skylineProblem.findSkyline(0, 0)); assertTrue(ex.getMessage().contains("not initialized")); - skylineProblem.building = new SkylineProblem.Building[2]; + skylineProblem.setBuilding(2); skylineProblem.count = 1; Exception ex2 = assertThrows(IllegalArgumentException.class, () -> skylineProblem.findSkyline(0, 1)); assertTrue(ex2.getMessage().contains("Invalid start or end index")); @@ -98,18 +98,8 @@ void testFindSkylineInvalidCases() { @Test void testMergeSkylineNullCases() { SkylineProblem skylineProblem = new SkylineProblem(); - Exception ex1 = assertThrows(NullPointerException.class, new org.junit.jupiter.api.function.Executable() { - @Override - public void execute() { - skylineProblem.mergeSkyline(null, List.of()); - } - }); - Exception ex2 = assertThrows(NullPointerException.class, new org.junit.jupiter.api.function.Executable() { - @Override - public void execute() { - skylineProblem.mergeSkyline(List.of(), null); - } - }); + Exception ex1 = assertThrows(NullPointerException.class, () -> skylineProblem.mergeSkyline(null, List.of())); + Exception ex2 = assertThrows(NullPointerException.class, () -> skylineProblem.mergeSkyline(List.of(), null)); assertTrue(ex1.getMessage().contains("sky1")); assertTrue(ex2.getMessage().contains("sky2")); } From f9e42d92525b2454b00a020df6260186f59e897a Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 5 Oct 2025 13:31:27 +0530 Subject: [PATCH 4/7] Fix --- .../bloomfilter/BloomFilter.java | 61 +++++++++++++++---- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java index d60b95110fc2..674047bdbbb6 100644 --- a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java +++ b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java @@ -1,18 +1,20 @@ package com.thealgorithms.datastructures.bloomfilter; +import java.util.Arrays; import java.util.BitSet; /** * A generic BloomFilter implementation for probabilistic membership checking. *

- * Bloom filters are space-efficient data structures that provide a fast way to test whether an - * element is a member of a set. They may produce false positives, indicating an element is + * Bloom filters are space-efficient data structures that provide a fast way to + * test whether an + * element is a member of a set. They may produce false positives, indicating an + * element is * in the set when it is not, but they will never produce false negatives. *

* * @param The type of elements to be stored in the Bloom filter. */ -@SuppressWarnings("rawtypes") public class BloomFilter { private final int numberOfHashFunctions; @@ -20,11 +22,14 @@ public class BloomFilter { private final Hash[] hashFunctions; /** - * Constructs a BloomFilter with a specified number of hash functions and bit array size. + * Constructs a BloomFilter with a specified number of hash functions and bit + * array size. * * @param numberOfHashFunctions the number of hash functions to use - * @param bitArraySize the size of the bit array, which determines the capacity of the filter - * @throws IllegalArgumentException if numberOfHashFunctions or bitArraySize is less than 1 + * @param bitArraySize the size of the bit array, which determines the + * capacity of the filter + * @throws IllegalArgumentException if numberOfHashFunctions or bitArraySize is + * less than 1 */ @SuppressWarnings("unchecked") public BloomFilter(int numberOfHashFunctions, int bitArraySize) { @@ -38,7 +43,8 @@ public BloomFilter(int numberOfHashFunctions, int bitArraySize) { } /** - * Initializes the hash functions with unique indices to ensure different hashing. + * Initializes the hash functions with unique indices to ensure different + * hashing. */ private void initializeHashFunctions() { for (int i = 0; i < numberOfHashFunctions; i++) { @@ -49,7 +55,8 @@ private void initializeHashFunctions() { /** * Inserts an element into the Bloom filter. *

- * This method hashes the element using all defined hash functions and sets the corresponding + * This method hashes the element using all defined hash functions and sets the + * corresponding * bits in the bit array. *

* @@ -65,13 +72,16 @@ public void insert(T key) { /** * Checks if an element might be in the Bloom filter. *

- * This method checks the bits at the positions computed by each hash function. If any of these - * bits are not set, the element is definitely not in the filter. If all bits are set, the element + * This method checks the bits at the positions computed by each hash function. + * If any of these + * bits are not set, the element is definitely not in the filter. If all bits + * are set, the element * might be in the filter. *

* * @param key the element to check for membership in the Bloom filter - * @return {@code true} if the element might be in the Bloom filter, {@code false} if it is definitely not + * @return {@code true} if the element might be in the Bloom filter, + * {@code false} if it is definitely not */ public boolean contains(T key) { for (Hash hash : hashFunctions) { @@ -86,7 +96,8 @@ public boolean contains(T key) { /** * Inner class representing a hash function used by the Bloom filter. *

- * Each instance of this class represents a different hash function based on its index. + * Each instance of this class represents a different hash function based on its + * index. *

* * @param The type of elements to be hashed. @@ -109,13 +120,37 @@ private static class Hash { *

* The hash value is calculated by multiplying the index of the hash function * with the ASCII sum of the string representation of the key. + * For array types, the content of the array is used instead of the default + * toString. *

* * @param key the element to hash * @return the computed hash value */ public int compute(T key) { - return index * asciiString(String.valueOf(key)); + String keyString; + if (key instanceof Object[] objectArray) { + keyString = Arrays.deepToString(objectArray); + } else if (key instanceof int[] intArray) { + keyString = Arrays.toString(intArray); + } else if (key instanceof long[] longArray) { + keyString = Arrays.toString(longArray); + } else if (key instanceof double[] doubleArray) { + keyString = Arrays.toString(doubleArray); + } else if (key instanceof float[] floatArray) { + keyString = Arrays.toString(floatArray); + } else if (key instanceof boolean[] booleanArray) { + keyString = Arrays.toString(booleanArray); + } else if (key instanceof byte[] byteArray) { + keyString = Arrays.toString(byteArray); + } else if (key instanceof char[] charArray) { + keyString = Arrays.toString(charArray); + } else if (key instanceof short[] shortArray) { + keyString = Arrays.toString(shortArray); + } else { + keyString = String.valueOf(key); + } + return index * asciiString(keyString); } /** From a72dec9aa681ed7a97312c2c35f6a24cc74140cc Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 5 Oct 2025 14:46:45 +0530 Subject: [PATCH 5/7] Fix --- .../thealgorithms/datastructures/bloomfilter/BloomFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java index 674047bdbbb6..98df154d4589 100644 --- a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java +++ b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java @@ -38,7 +38,7 @@ public BloomFilter(int numberOfHashFunctions, int bitArraySize) { } this.numberOfHashFunctions = numberOfHashFunctions; this.bitArray = new BitSet(bitArraySize); - this.hashFunctions = new Hash[numberOfHashFunctions]; + this.hashFunctions = (Hash[]) new Hash[numberOfHashFunctions]; initializeHashFunctions(); } From 63fd91ded7141df2b8537c102011cf2b127dacef Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 12 Oct 2025 11:21:02 +0530 Subject: [PATCH 6/7] Fix reviews --- .../bloomfilter/BloomFilter.java | 34 +++++++------------ .../thealgorithms/others/SkylineProblem.java | 1 - 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java index 98df154d4589..610937950c16 100644 --- a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java +++ b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java @@ -128,28 +128,18 @@ private static class Hash { * @return the computed hash value */ public int compute(T key) { - String keyString; - if (key instanceof Object[] objectArray) { - keyString = Arrays.deepToString(objectArray); - } else if (key instanceof int[] intArray) { - keyString = Arrays.toString(intArray); - } else if (key instanceof long[] longArray) { - keyString = Arrays.toString(longArray); - } else if (key instanceof double[] doubleArray) { - keyString = Arrays.toString(doubleArray); - } else if (key instanceof float[] floatArray) { - keyString = Arrays.toString(floatArray); - } else if (key instanceof boolean[] booleanArray) { - keyString = Arrays.toString(booleanArray); - } else if (key instanceof byte[] byteArray) { - keyString = Arrays.toString(byteArray); - } else if (key instanceof char[] charArray) { - keyString = Arrays.toString(charArray); - } else if (key instanceof short[] shortArray) { - keyString = Arrays.toString(shortArray); - } else { - keyString = String.valueOf(key); - } + String keyString = switch (key) { + case Object[] arr -> Arrays.deepToString(arr); + case int[] arr -> Arrays.toString(arr); + case long[] arr -> Arrays.toString(arr); + case double[] arr -> Arrays.toString(arr); + case float[] arr -> Arrays.toString(arr); + case boolean[] arr -> Arrays.toString(arr); + case byte[] arr -> Arrays.toString(arr); + case char[] arr -> Arrays.toString(arr); + case short[] arr -> Arrays.toString(arr); + case null, default -> String.valueOf(key); + }; return index * asciiString(keyString); } diff --git a/src/main/java/com/thealgorithms/others/SkylineProblem.java b/src/main/java/com/thealgorithms/others/SkylineProblem.java index 470d861664ad..d9e2a8cc2547 100644 --- a/src/main/java/com/thealgorithms/others/SkylineProblem.java +++ b/src/main/java/com/thealgorithms/others/SkylineProblem.java @@ -1,4 +1,3 @@ - package com.thealgorithms.others; import java.util.ArrayList; From 582908b3105b9699a031502813e8a31575738254 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Sun, 12 Oct 2025 11:21:26 +0530 Subject: [PATCH 7/7] Lint --- .../datastructures/bloomfilter/BloomFilter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java index 610937950c16..8c4204e1239f 100644 --- a/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java +++ b/src/main/java/com/thealgorithms/datastructures/bloomfilter/BloomFilter.java @@ -156,9 +156,9 @@ public int compute(T key) { private int asciiString(String word) { int sum = 0; for (char c : word.toCharArray()) { - sum += c; - } - return sum; + sum += c; + } + return sum; + } } } -}