From 0890b1432a342a0d5eaeca84a3ef96d21755a920 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 16 Feb 2025 09:57:31 +0200 Subject: [PATCH 01/11] Added tasks 3451-3459 --- .../s3451_find_invalid_ip_addresses/readme.md | 61 +++++++ .../script.sql | 15 ++ .../s3452_sum_of_good_numbers/Solution.java | 27 +++ .../s3452_sum_of_good_numbers/readme.md | 33 ++++ .../s3453_separate_squares_i/Solution.java | 42 +++++ .../s3453_separate_squares_i/readme.md | 48 +++++ .../s3454_separate_squares_ii/Solution.java | 172 ++++++++++++++++++ .../s3454_separate_squares_ii/readme.md | 43 +++++ .../Solution.java | 79 ++++++++ .../readme.md | 58 ++++++ .../Solution.java | 36 ++++ .../readme.md | 43 +++++ .../g3401_3500/s3457_eat_pizzas/Solution.java | 26 +++ .../g3401_3500/s3457_eat_pizzas/readme.md | 44 +++++ .../Solution.java | 82 +++++++++ .../readme.md | 48 +++++ .../Solution.java | 59 ++++++ .../readme.md | 71 ++++++++ .../MysqlTest.java | 70 +++++++ .../SolutionTest.java | 18 ++ .../SolutionTest.java | 22 +++ .../SolutionTest.java | 20 ++ .../SolutionTest.java | 30 +++ .../SolutionTest.java | 18 ++ .../s3457_eat_pizzas/SolutionTest.java | 18 ++ .../SolutionTest.java | 23 +++ .../SolutionTest.java | 53 ++++++ 27 files changed, 1259 insertions(+) create mode 100644 src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/readme.md create mode 100644 src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/script.sql create mode 100644 src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java create mode 100644 src/main/java/g3401_3500/s3452_sum_of_good_numbers/readme.md create mode 100644 src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java create mode 100644 src/main/java/g3401_3500/s3453_separate_squares_i/readme.md create mode 100644 src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java create mode 100644 src/main/java/g3401_3500/s3454_separate_squares_ii/readme.md create mode 100644 src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java create mode 100644 src/main/java/g3401_3500/s3455_shortest_matching_substring/readme.md create mode 100644 src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java create mode 100644 src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/readme.md create mode 100644 src/main/java/g3401_3500/s3457_eat_pizzas/Solution.java create mode 100644 src/main/java/g3401_3500/s3457_eat_pizzas/readme.md create mode 100644 src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java create mode 100644 src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/readme.md create mode 100644 src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/Solution.java create mode 100644 src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/readme.md create mode 100644 src/test/java/g3401_3500/s3451_find_invalid_ip_addresses/MysqlTest.java create mode 100644 src/test/java/g3401_3500/s3452_sum_of_good_numbers/SolutionTest.java create mode 100644 src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java create mode 100644 src/test/java/g3401_3500/s3454_separate_squares_ii/SolutionTest.java create mode 100644 src/test/java/g3401_3500/s3455_shortest_matching_substring/SolutionTest.java create mode 100644 src/test/java/g3401_3500/s3456_find_special_substring_of_length_k/SolutionTest.java create mode 100644 src/test/java/g3401_3500/s3457_eat_pizzas/SolutionTest.java create mode 100644 src/test/java/g3401_3500/s3458_select_k_disjoint_special_substrings/SolutionTest.java create mode 100644 src/test/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/SolutionTest.java diff --git a/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/readme.md b/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/readme.md new file mode 100644 index 000000000..458a6a95e --- /dev/null +++ b/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/readme.md @@ -0,0 +1,61 @@ +3451\. Find Invalid IP Addresses + +Hard + +Table: `logs` + + +-------------+---------+ + | Column Name | Type | + +-------------+---------+ + | log_id | int | + | ip | varchar | + | status_code | int | + +-------------+---------+ + log_id is the unique key for this table. + Each row contains server access log information including IP address and HTTP status code. + +Write a solution to find **invalid IP addresses**. An IPv4 address is invalid if it meets any of these conditions: + +* Contains numbers **greater than** `255` in any octet +* Has **leading zeros** in any octet (like `01.02.03.04`) +* Has **less or more** than `4` octets + +Return _the result table_ _ordered by_ `invalid_count`, `ip` _in **descending** order respectively_. + +The result format is in the following example. + +**Example:** + +**Input:** + +logs table: + + +--------+---------------+-------------+ + | log_id | ip | status_code | + +--------+---------------+-------------+ + | 1 | 192.168.1.1 | 200 | + | 2 | 256.1.2.3 | 404 | + | 3 | 192.168.001.1 | 200 | + | 4 | 192.168.1.1 | 200 | + | 5 | 192.168.1 | 500 | + | 6 | 256.1.2.3 | 404 | + | 7 | 192.168.001.1 | 200 | + +--------+---------------+-------------+ + +**Output:** + + +---------------+--------------+ + | ip | invalid_count| + +---------------+--------------+ + | 256.1.2.3 | 2 | + | 192.168.001.1 | 2 | + | 192.168.1 | 1 | + +---------------+--------------+ + +**Explanation:** + +* 256.1.2.3 is invalid because 256 > 255 +* 192.168.001.1 is invalid because of leading zeros +* 192.168.1 is invalid because it has only 3 octets + +The output table is ordered by invalid\_count, ip in descending order respectively. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/script.sql b/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/script.sql new file mode 100644 index 000000000..77e206f5d --- /dev/null +++ b/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/script.sql @@ -0,0 +1,15 @@ +# Write your MySQL query statement below +# #Hard #2025_02_16_Time_383_ms_(85.47%)_Space_0.0_MB_(100.00%) +WITH cte_invalid_ip AS ( + SELECT log_id, ip + FROM logs + WHERE NOT regexp_like(ip, '^(?:[1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(?:[.](?:[1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$') + ), + cte_invalid_ip_count AS ( + SELECT ip, count(log_id) as invalid_count + FROM cte_invalid_ip + GROUP BY ip + ) +SELECT ip, invalid_count +FROM cte_invalid_ip_count +ORDER BY invalid_count DESC, ip DESC; diff --git a/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java b/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java new file mode 100644 index 000000000..02a47f034 --- /dev/null +++ b/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java @@ -0,0 +1,27 @@ +package g3401_3500.s3452_sum_of_good_numbers; + +// #Easy #2025_02_16_Time_1_ms_(100.00%)_Space_44.30_MB_(100.00%) + +public class Solution { + public int sumOfGoodNumbers(int[] nums, int k) { + int totalSum = 0; + int n = nums.length; + for (int i = 0; i < n; i++) { + boolean isGood = true; + if (i - k >= 0) { + if (nums[i] <= nums[i - k]) { + isGood = false; + } + } + if (i + k < n) { + if (nums[i] <= nums[i + k]) { + isGood = false; + } + } + if (isGood) { + totalSum += nums[i]; + } + } + return totalSum; + } +} diff --git a/src/main/java/g3401_3500/s3452_sum_of_good_numbers/readme.md b/src/main/java/g3401_3500/s3452_sum_of_good_numbers/readme.md new file mode 100644 index 000000000..f6a899293 --- /dev/null +++ b/src/main/java/g3401_3500/s3452_sum_of_good_numbers/readme.md @@ -0,0 +1,33 @@ +3452\. Sum of Good Numbers + +Easy + +Given an array of integers `nums` and an integer `k`, an element `nums[i]` is considered **good** if it is **strictly** greater than the elements at indices `i - k` and `i + k` (if those indices exist). If neither of these indices _exists_, `nums[i]` is still considered **good**. + +Return the **sum** of all the **good** elements in the array. + +**Example 1:** + +**Input:** nums = [1,3,2,1,5,4], k = 2 + +**Output:** 12 + +**Explanation:** + +The good numbers are `nums[1] = 3`, `nums[4] = 5`, and `nums[5] = 4` because they are strictly greater than the numbers at indices `i - k` and `i + k`. + +**Example 2:** + +**Input:** nums = [2,1], k = 1 + +**Output:** 2 + +**Explanation:** + +The only good number is `nums[0] = 2` because it is strictly greater than `nums[1]`. + +**Constraints:** + +* `2 <= nums.length <= 100` +* `1 <= nums[i] <= 1000` +* `1 <= k <= floor(nums.length / 2)` \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java b/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java new file mode 100644 index 000000000..81aa081d2 --- /dev/null +++ b/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java @@ -0,0 +1,42 @@ +package g3401_3500.s3453_separate_squares_i; + +// #Medium #2025_02_16_Time_123_ms_(100.00%)_Space_87.97_MB_(_%) + +public class Solution { + private double helper(double line, int[][] squares) { + double aAbove = 0; + double aBelow = 0; + for (int[] square : squares) { + int y = square[1]; + int l = square[2]; + double total = (double) l * l; + if (line <= y) { + aAbove += total; + } else if (line >= y + l) { + aBelow += total; + } else { + // The line intersects the square. + double aboveHeight = (y + l) - line; + double belowHeight = line - y; + aAbove += l * aboveHeight; + aBelow += l * belowHeight; + } + } + return aAbove - aBelow; + } + + public double separateSquares(int[][] squares) { + double lo = 0; + double hi = 2 * 1e9; + for (int i = 0; i < 60; i++) { + double mid = (lo + hi) / 2.0; + double diff = helper(mid, squares); + if (diff > 0) { + lo = mid; + } else { + hi = mid; + } + } + return hi; + } +} diff --git a/src/main/java/g3401_3500/s3453_separate_squares_i/readme.md b/src/main/java/g3401_3500/s3453_separate_squares_i/readme.md new file mode 100644 index 000000000..19f128d6e --- /dev/null +++ b/src/main/java/g3401_3500/s3453_separate_squares_i/readme.md @@ -0,0 +1,48 @@ +3453\. Separate Squares I + +Medium + +You are given a 2D integer array `squares`. Each squares[i] = [xi, yi, li] represents the coordinates of the bottom-left point and the side length of a square parallel to the x-axis. + +Find the **minimum** y-coordinate value of a horizontal line such that the total area of the squares above the line _equals_ the total area of the squares below the line. + +Answers within 10-5 of the actual answer will be accepted. + +**Note**: Squares **may** overlap. Overlapping areas should be counted **multiple times**. + +**Example 1:** + +**Input:** squares = [[0,0,1],[2,2,1]] + +**Output:** 1.00000 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/01/06/4062example1drawio.png) + +Any horizontal line between `y = 1` and `y = 2` will have 1 square unit above it and 1 square unit below it. The lowest option is 1. + +**Example 2:** + +**Input:** squares = [[0,0,2],[1,1,1]] + +**Output:** 1.16667 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/01/15/4062example2drawio.png) + +The areas are: + +* Below the line: `7/6 * 2 (Red) + 1/6 (Blue) = 15/6 = 2.5`. +* Above the line: `5/6 * 2 (Red) + 5/6 (Blue) = 15/6 = 2.5`. + +Since the areas above and below the line are equal, the output is `7/6 = 1.16667`. + +**Constraints:** + +* 1 <= squares.length <= 5 * 104 +* squares[i] = [xi, yi, li] +* `squares[i].length == 3` +* 0 <= xi, yi <= 109 +* 1 <= li <= 109 \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java new file mode 100644 index 000000000..ab0dec617 --- /dev/null +++ b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java @@ -0,0 +1,172 @@ +package g3401_3500.s3454_separate_squares_ii; + +// #Hard #2025_02_16_Time_243_ms_(100.00%)_Space_76.06_MB_(100.00%) + +import java.util.Arrays; +import java.util.Comparator; + +public class Solution { + public double separateSquares(int[][] squares) { + int n = squares.length; + int m = 2 * n; + Event[] events = new Event[m]; + double[] xsRaw = new double[m]; + int idx = 0; + int xIdx = 0; + for (int[] sq : squares) { + // Each square gives a rectangle [x, x+l] x [y, y+l] + double x = sq[0]; + double y = sq[1]; + double l = sq[2]; + double x2 = x + l; + double y2 = y + l; + events[idx++] = new Event(y, x, x2, 1); + events[idx++] = new Event(y2, x, x2, -1); + xsRaw[xIdx++] = x; + xsRaw[xIdx++] = x2; + } + // Sort events by their y-coordinate (they are exact integers in double format) + Arrays.sort(events, Comparator.comparingDouble(e -> e.y)); + // Compress x-coordinates + double[] xs = compress(xsRaw); + // FIRST SWEEP: compute total union area. + SegmentTree segTree = new SegmentTree(xs); + double totalUnionArea = 0.0; + double lastY = events[0].y; + for (int i = 0; i < m; ) { + double curY = events[i].y; + if (curY > lastY) { + double unionX = segTree.query(); + totalUnionArea += unionX * (curY - lastY); + lastY = curY; + } + // Process all events at y == curY + while (i < m && events[i].y == curY) { + int lIdx = Arrays.binarySearch(xs, events[i].x1); + if (lIdx < 0) { + lIdx = -lIdx - 1; + } + int rIdx = Arrays.binarySearch(xs, events[i].x2); + if (rIdx < 0) { + rIdx = -rIdx - 1; + } + segTree.update(1, 0, xs.length - 1, lIdx, rIdx, events[i].type); + i++; + } + } + double target = totalUnionArea / 2.0; + // SECOND SWEEP: find minimal y such that cumulative union area reaches target. + // Reinitialize segment tree for a fresh sweep. + segTree = new SegmentTree(xs); + lastY = events[0].y; + double cumArea = 0.0; + for (int i = 0; i < m; ) { + double curY = events[i].y; + if (curY > lastY) { + double unionX = segTree.query(); + double dy = curY - lastY; + if (cumArea + unionX * dy >= target - 1e-10) { + // The answer lies in this interval. + return lastY + (target - cumArea) / unionX; + } + cumArea += unionX * dy; + lastY = curY; + } + while (i < m && events[i].y == curY) { + int lIdx = Arrays.binarySearch(xs, events[i].x1); + if (lIdx < 0) { + lIdx = -lIdx - 1; + } + int rIdx = Arrays.binarySearch(xs, events[i].x2); + if (rIdx < 0) { + rIdx = -rIdx - 1; + } + segTree.update(1, 0, xs.length - 1, lIdx, rIdx, events[i].type); + i++; + } + } + return lastY; + } + + // Compress an array of doubles into a sorted array of unique values. + private double[] compress(double[] arr) { + Arrays.sort(arr); + int cnt = 1; + for (int i = 1; i < arr.length; i++) { + if (arr[i] != arr[i - 1]) { + cnt++; + } + } + double[] res = new double[cnt]; + res[0] = arr[0]; + int j = 1; + for (int i = 1; i < arr.length; i++) { + if (arr[i] != arr[i - 1]) { + res[j++] = arr[i]; + } + } + return res; + } + + // Event class for the sweep-line. + private static class Event { + double y; + double x1; + double x2; + // +1 for adding an interval; -1 for removing. + int type; + + Event(double y, double x1, double x2, int type) { + this.y = y; + this.x1 = x1; + this.x2 = x2; + this.type = type; + } + } + + // Segment Tree for maintaining the union length over the x-axis. + private static class SegmentTree { + int n; + // Covered length of the segment. + double[] tree; + // Coverage count for the segment. + int[] count; + // The compressed x-coordinates. + double[] xs; + + SegmentTree(double[] xs) { + this.xs = xs; + this.n = xs.length; + // Allocate 4*n size arrays. + tree = new double[4 * n]; + count = new int[4 * n]; + } + + // Update the range [ql, qr) with value 'val'. + // The current node covers indices [l, r) in xs. + void update(int idx, int l, int r, int ql, int qr, int val) { + if (qr <= l || ql >= r) { + return; + } + if (ql <= l && r <= qr) { + count[idx] += val; + } else { + int mid = (l + r) >> 1; + update(idx << 1, l, mid, ql, qr, val); + update(idx << 1 | 1, mid, r, ql, qr, val); + } + if (count[idx] > 0) { + tree[idx] = xs[r] - xs[l]; + } else if (r - l == 1) { + tree[idx] = 0; + } else { + tree[idx] = tree[idx << 1] + tree[idx << 1 | 1]; + } + } + + // Query the current total union length. + double query() { + return tree[1]; + } + } +} diff --git a/src/main/java/g3401_3500/s3454_separate_squares_ii/readme.md b/src/main/java/g3401_3500/s3454_separate_squares_ii/readme.md new file mode 100644 index 000000000..741da7dce --- /dev/null +++ b/src/main/java/g3401_3500/s3454_separate_squares_ii/readme.md @@ -0,0 +1,43 @@ +3454\. Separate Squares II + +Hard + +You are given a 2D integer array `squares`. Each squares[i] = [xi, yi, li] represents the coordinates of the bottom-left point and the side length of a square parallel to the x-axis. + +Find the **minimum** y-coordinate value of a horizontal line such that the total area covered by squares above the line _equals_ the total area covered by squares below the line. + +Answers within 10-5 of the actual answer will be accepted. + +**Note**: Squares **may** overlap. Overlapping areas should be counted **only once** in this version. + +**Example 1:** + +**Input:** squares = [[0,0,1],[2,2,1]] + +**Output:** 1.00000 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/01/15/4065example1drawio.png) + +Any horizontal line between `y = 1` and `y = 2` results in an equal split, with 1 square unit above and 1 square unit below. The minimum y-value is 1. + +**Example 2:** + +**Input:** squares = [[0,0,2],[1,1,1]] + +**Output:** 1.00000 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/01/15/4065example2drawio.png) + +Since the blue square overlaps with the red square, it will not be counted again. Thus, the line `y = 1` splits the squares into two equal parts. + +**Constraints:** + +* 1 <= squares.length <= 5 * 104 +* squares[i] = [xi, yi, li] +* `squares[i].length == 3` +* 0 <= xi, yi <= 109 +* 1 <= li <= 109 \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java new file mode 100644 index 000000000..0ab193ada --- /dev/null +++ b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java @@ -0,0 +1,79 @@ +package g3401_3500.s3455_shortest_matching_substring; + +// #Hard #2025_02_16_Time_976_ms_(100.00%)_Space_45.76_MB_(100.00%) + +public class Solution { + public int shortestMatchingSubstring(String s, String p) { + int minLen = Integer.MAX_VALUE; + String[] ar = p.split("\\*"); + int arlen = ar.length; + if (arlen == 0) { + return 0; + } + String temp = p.replace("*", ""); + if (s.contains(temp)) { + return temp.length(); + } + int f = s.indexOf(ar[0]); + while (f != -1) { + int shortLen = Integer.MAX_VALUE; + if (arlen > 1) { + int sec = s.indexOf(ar[1], f + ar[0].length()); + while (sec != -1) { + if (ar[0].isEmpty()) { + f = sec; + } + if (arlen > 2) { + int third = s.indexOf(ar[2], sec + ar[1].length()); + if (third != -1) { + if (ar[0].isEmpty() && ar[1].isEmpty()) { + f = third; + } + shortLen = third + ar[2].length() - f; + minLen = Math.min(shortLen, minLen); + if (minLen == p.length() - 2) { + return minLen; + } + if (minLen == Integer.MAX_VALUE) { + return -1; + } + } + } else { + shortLen = sec + ar[1].length() - f; + minLen = Math.min(shortLen, minLen); + } + if (minLen == p.length() - 2) { + return minLen; + } + if (ar[1].isEmpty()) { + sec = -1; + } else { + sec = s.indexOf(ar[1], sec + 1); + } + if (minLen == Integer.MAX_VALUE) { + return -1; + } + } + } else { + shortLen = f + ar[0].length() - f; + minLen = shortLen; + } + minLen = Math.min(shortLen, minLen); + if (minLen == p.length() - 2) { + return minLen; + } + if (ar[0].isEmpty()) { + f = -1; + } else { + f = s.indexOf(ar[0], f + 1); + } + if (minLen == Integer.MAX_VALUE) { + return -1; + } + } + if (minLen == Integer.MAX_VALUE) { + return -1; + } + return minLen; + } +} diff --git a/src/main/java/g3401_3500/s3455_shortest_matching_substring/readme.md b/src/main/java/g3401_3500/s3455_shortest_matching_substring/readme.md new file mode 100644 index 000000000..988440eca --- /dev/null +++ b/src/main/java/g3401_3500/s3455_shortest_matching_substring/readme.md @@ -0,0 +1,58 @@ +3455\. Shortest Matching Substring + +Hard + +You are given a string `s` and a pattern string `p`, where `p` contains **exactly two** `'*'` characters. + +The `'*'` in `p` matches any sequence of zero or more characters. + +Return the length of the **shortest** **substring** in `s` that matches `p`. If there is no such substring, return -1. + +**Note:** The empty substring is considered valid. + +**Example 1:** + +**Input:** s = "abaacbaecebce", p = "ba\*c\*ce" + +**Output:** 8 + +**Explanation:** + +The shortest matching substring of `p` in `s` is "**ba**e**c**eb**ce**". + +**Example 2:** + +**Input:** s = "baccbaadbc", p = "cc\*baa\*adb" + +**Output:** \-1 + +**Explanation:** + +There is no matching substring in `s`. + +**Example 3:** + +**Input:** s = "a", p = "\*\*" + +**Output:** 0 + +**Explanation:** + +The empty substring is the shortest matching substring. + +**Example 4:** + +**Input:** s = "madlogic", p = "\*adlogi\*" + +**Output:** 6 + +**Explanation:** + +The shortest matching substring of `p` in `s` is "**adlogi**". + +**Constraints:** + +* 1 <= s.length <= 105 +* 2 <= p.length <= 105 +* `s` contains only lowercase English letters. +* `p` contains only lowercase English letters and exactly two `'*'`. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java new file mode 100644 index 000000000..3457210a6 --- /dev/null +++ b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java @@ -0,0 +1,36 @@ +package g3401_3500.s3456_find_special_substring_of_length_k; + +// #Easy #2025_02_16_Time_1_ms_(100.00%)_Space_42.04_MB_(100.00%) + +public class Solution { + public boolean hasSpecialSubstring(String s, int k) { + // 🚫 If string is smaller than k, no valid substring exists + if (s.length() < k) { + return false; + } + // 🔍 Iterate through all possible substrings of length k + for (int i = 0; i <= s.length() - k; i++) { + // 🧮 Count consecutive identical characters + int count = 1; + // ✅ Check if all k characters in the substring are the same + for (int j = i; j < i + k - 1; j++) { + if (s.charAt(j) == s.charAt(j + 1)) { + // ➕ Increase count if consecutive characters are the same + count++; + } else { + // ❌ Break if mismatch occurs + break; + } + } + // 🔎 Ensure the substring is not part of a larger group + if (count == k + && (i == 0 || s.charAt(i - 1) != s.charAt(i)) + && (i + k == s.length() || s.charAt(i + k) != s.charAt(i))) { + // 🎯 Found a valid special substring + return true; + } + } + // ❌ No valid substring found + return false; + } +} diff --git a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/readme.md b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/readme.md new file mode 100644 index 000000000..32c7b48c8 --- /dev/null +++ b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/readme.md @@ -0,0 +1,43 @@ +3456\. Find Special Substring of Length K + +Easy + +You are given a string `s` and an integer `k`. + +Determine if there exists a **substring** of length **exactly** `k` in `s` that satisfies the following conditions: + +1. The substring consists of **only one distinct character** (e.g., `"aaa"` or `"bbb"`). +2. If there is a character **immediately before** the substring, it must be different from the character in the substring. +3. If there is a character **immediately after** the substring, it must also be different from the character in the substring. + +Return `true` if such a substring exists. Otherwise, return `false`. + +**Example 1:** + +**Input:** s = "aaabaaa", k = 3 + +**Output:** true + +**Explanation:** + +The substring `s[4..6] == "aaa"` satisfies the conditions. + +* It has a length of 3. +* All characters are the same. +* The character before `"aaa"` is `'b'`, which is different from `'a'`. +* There is no character after `"aaa"`. + +**Example 2:** + +**Input:** s = "abc", k = 2 + +**Output:** false + +**Explanation:** + +There is no substring of length 2 that consists of one distinct character and satisfies the conditions. + +**Constraints:** + +* `1 <= k <= s.length <= 100` +* `s` consists of lowercase English letters only. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3457_eat_pizzas/Solution.java b/src/main/java/g3401_3500/s3457_eat_pizzas/Solution.java new file mode 100644 index 000000000..696b35b08 --- /dev/null +++ b/src/main/java/g3401_3500/s3457_eat_pizzas/Solution.java @@ -0,0 +1,26 @@ +package g3401_3500.s3457_eat_pizzas; + +// #Medium #2025_02_16_Time_64_ms_(100.00%)_Space_80.85_MB_(100.00%) + +import java.util.Arrays; + +public class Solution { + public long maxWeight(int[] pizzas) { + int n = pizzas.length; + int m = n / 4; + int z = (m + 1) / 2; + int y = m / 2; + int j = 0; + Arrays.sort(pizzas); + long res = 0; + for (int i = 0; i < z; ++i) { + res += pizzas[n - 1 - j]; + j += 1; + } + for (int i = 0; i < y; ++i) { + res += pizzas[n - 1 - j - 1]; + j += 2; + } + return res; + } +} diff --git a/src/main/java/g3401_3500/s3457_eat_pizzas/readme.md b/src/main/java/g3401_3500/s3457_eat_pizzas/readme.md new file mode 100644 index 000000000..fa6b270b8 --- /dev/null +++ b/src/main/java/g3401_3500/s3457_eat_pizzas/readme.md @@ -0,0 +1,44 @@ +3457\. Eat Pizzas! + +Medium + +You are given an integer array `pizzas` of size `n`, where `pizzas[i]` represents the weight of the ith pizza. Every day, you eat **exactly** 4 pizzas. Due to your incredible metabolism, when you eat pizzas of weights `W`, `X`, `Y`, and `Z`, where `W <= X <= Y <= Z`, you gain the weight of only 1 pizza! + +* On **odd-numbered** days **(1-indexed)**, you gain a weight of `Z`. +* On **even-numbered** days, you gain a weight of `Y`. + +Find the **maximum** total weight you can gain by eating **all** pizzas optimally. + +**Note**: It is guaranteed that `n` is a multiple of 4, and each pizza can be eaten only once. + +**Example 1:** + +**Input:** pizzas = [1,2,3,4,5,6,7,8] + +**Output:** 14 + +**Explanation:** + +* On day 1, you eat pizzas at indices `[1, 2, 4, 7] = [2, 3, 5, 8]`. You gain a weight of 8. +* On day 2, you eat pizzas at indices `[0, 3, 5, 6] = [1, 4, 6, 7]`. You gain a weight of 6. + +The total weight gained after eating all the pizzas is `8 + 6 = 14`. + +**Example 2:** + +**Input:** pizzas = [2,1,1,1,1,1,1,1] + +**Output:** 3 + +**Explanation:** + +* On day 1, you eat pizzas at indices `[4, 5, 6, 0] = [1, 1, 1, 2]`. You gain a weight of 2. +* On day 2, you eat pizzas at indices `[1, 2, 3, 7] = [1, 1, 1, 1]`. You gain a weight of 1. + +The total weight gained after eating all the pizzas is `2 + 1 = 3.` + +**Constraints:** + +* 4 <= n == pizzas.length <= 2 * 105 +* 1 <= pizzas[i] <= 105 +* `n` is a multiple of 4. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java b/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java new file mode 100644 index 000000000..80f269bb0 --- /dev/null +++ b/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java @@ -0,0 +1,82 @@ +package g3401_3500.s3458_select_k_disjoint_special_substrings; + +// #Medium #2025_02_16_Time_21_ms_(100.00%)_Space_45.30_MB_(100.00%) + +import java.util.Arrays; + +public class Solution { + public boolean maxSubstringLength(String s, int k) { + char[] arr = s.toCharArray(); + int n = arr.length; + int[][] freq = new int[2][26]; + for (int[] is : freq) { + Arrays.fill(is, -1); + } + for (int i = 0; i < n; i++) { + int x = arr[i] - 97; + if (freq[0][x] == -1) { + freq[0][x] = i; + } + freq[1][x] = i; + } + for (int i = 0; i < 26; i++) { + if (freq[0][i] == -1) { + continue; + } + int max = freq[1][i]; + int min = freq[0][i]; + for (int j = freq[0][i]; j <= freq[1][i]; j++) { + max = Math.max(max, freq[1][arr[j] - 'a']); + min = Math.min(min, freq[0][arr[j] - 'a']); + } + freq[1][i] = max; + freq[0][i] = min; + } + int[][] temp = new int[2][26]; + int x = 0; + for (int i = 0; i < 26; i++) { + if (freq[0][i] != -1) { + temp[0][x] = freq[0][i]; + temp[1][x] = freq[1][i]; + if (temp[1][x] == -1) { + temp[1][x] = temp[0][x]; + } + x++; + } + } + int[][] nums = new int[x][2]; + for (int i = 0; i < x; i++) { + nums[i][0] = temp[0][i]; + nums[i][1] = temp[1][i]; + } + Arrays.sort(nums, (a, b) -> a[0] - b[0]); + int[][] ans = new int[x][2]; + int y = 0; + for (int i = 0; i < x; i++) { + if (y == 0) { + ans[y][0] = nums[i][0]; + ans[y][1] = nums[i][1]; + y++; + } else { + if (ans[y - 1][1] > nums[i][0]) { + if (ans[y - 1][1] < nums[i][1]) { + continue; + } + ans[y - 1][0] = nums[i][0]; + ans[y - 1][1] = nums[i][1]; + } else { + ans[y][0] = nums[i][0]; + ans[y][1] = nums[i][1]; + y++; + } + } + } + if (y >= k) { + if (y == 1 && k == 1) { + return ans[0][0] != 0 || ans[0][1] != n - 1; + } + return true; + } + return false; + } +} diff --git a/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/readme.md b/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/readme.md new file mode 100644 index 000000000..139f85290 --- /dev/null +++ b/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/readme.md @@ -0,0 +1,48 @@ +3458\. Select K Disjoint Special Substrings + +Medium + +Given a string `s` of length `n` and an integer `k`, determine whether it is possible to select `k` disjoint **special substrings**. + +A **special substring** is a **substring** where: + +* Any character present inside the substring should not appear outside it in the string. +* The substring is not the entire string `s`. + +**Note** that all `k` substrings must be disjoint, meaning they cannot overlap. + +Return `true` if it is possible to select `k` such disjoint special substrings; otherwise, return `false`. + +**Example 1:** + +**Input:** s = "abcdbaefab", k = 2 + +**Output:** true + +**Explanation:** + +* We can select two disjoint special substrings: `"cd"` and `"ef"`. +* `"cd"` contains the characters `'c'` and `'d'`, which do not appear elsewhere in `s`. +* `"ef"` contains the characters `'e'` and `'f'`, which do not appear elsewhere in `s`. + +**Example 2:** + +**Input:** s = "cdefdc", k = 3 + +**Output:** false + +**Explanation:** + +There can be at most 2 disjoint special substrings: `"e"` and `"f"`. Since `k = 3`, the output is `false`. + +**Example 3:** + +**Input:** s = "abeabe", k = 0 + +**Output:** true + +**Constraints:** + +* 2 <= n == s.length <= 5 * 104 +* `0 <= k <= 26` +* `s` consists only of lowercase English letters. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/Solution.java b/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/Solution.java new file mode 100644 index 000000000..f370c6032 --- /dev/null +++ b/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/Solution.java @@ -0,0 +1,59 @@ +package g3401_3500.s3459_length_of_longest_v_shaped_diagonal_segment; + +// #Hard #2025_02_16_Time_484_ms_(100.00%)_Space_139.26_MB_(_%) + +import java.util.Arrays; + +public class Solution { + private final int[][] ds = {{1, 1}, {1, -1}, {-1, -1}, {-1, 1}}; + private final int[] nx = {2, 2, 0}; + private int[][] grid; + private int n; + private int m; + private int[][][][] dp; + + public int lenOfVDiagonal(int[][] g) { + this.grid = g; + this.n = g.length; + this.m = g[0].length; + this.dp = new int[n][m][4][2]; + for (int[][][] d1 : dp) { + for (int[][] d2 : d1) { + for (int[] d3 : d2) { + Arrays.fill(d3, -1); + } + } + } + int res = 0; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (g[i][j] == 1) { + for (int d = 0; d < 4; d++) { + res = Math.max(res, dp(i, j, 1, d, 1)); + } + } + } + } + return res; + } + + private int dp(int i, int j, int x, int d, int k) { + if (i < 0 || i >= n || j < 0 || j >= m) { + return 0; + } + if (grid[i][j] != x) { + return 0; + } + if (dp[i][j][d][k] != -1) { + return dp[i][j][d][k]; + } + int res = dp(i + ds[d][0], j + ds[d][1], nx[x], d, k) + 1; + if (k > 0) { + int d2 = (d + 1) % 4; + int res2 = dp(i + ds[d2][0], j + ds[d2][1], nx[x], d2, 0) + 1; + res = Math.max(res, res2); + } + dp[i][j][d][k] = res; + return res; + } +} diff --git a/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/readme.md b/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/readme.md new file mode 100644 index 000000000..0745db140 --- /dev/null +++ b/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/readme.md @@ -0,0 +1,71 @@ +3459\. Length of Longest V-Shaped Diagonal Segment + +Hard + +You are given a 2D integer matrix `grid` of size `n x m`, where each element is either `0`, `1`, or `2`. + +A **V-shaped diagonal segment** is defined as: + +* The segment starts with `1`. +* The subsequent elements follow this infinite sequence: `2, 0, 2, 0, ...`. +* The segment: + * Starts **along** a diagonal direction (top-left to bottom-right, bottom-right to top-left, top-right to bottom-left, or bottom-left to top-right). + * Continues the **sequence** in the same diagonal direction. + * Makes **at most one clockwise 90-degree** **turn** to another diagonal direction while **maintaining** the sequence. + +![](https://assets.leetcode.com/uploads/2025/01/11/length_of_longest3.jpg) + +Return the **length** of the **longest** **V-shaped diagonal segment**. If no valid segment _exists_, return 0. + +**Example 1:** + +**Input:** grid = [[2,2,1,2,2],[2,0,2,2,0],[2,0,1,1,0],[1,0,2,2,2],[2,0,0,2,2]] + +**Output:** 5 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2024/12/09/matrix_1-2.jpg) + +The longest V-shaped diagonal segment has a length of 5 and follows these coordinates: `(0,2) → (1,3) → (2,4)`, takes a **90-degree clockwise turn** at `(2,4)`, and continues as `(3,3) → (4,2)`. + +**Example 2:** + +**Input:** grid = [[2,2,2,2,2],[2,0,2,2,0],[2,0,1,1,0],[1,0,2,2,2],[2,0,0,2,2]] + +**Output:** 4 + +**Explanation:** + +**![](https://assets.leetcode.com/uploads/2024/12/09/matrix_2.jpg)** + +The longest V-shaped diagonal segment has a length of 4 and follows these coordinates: `(2,3) → (3,2)`, takes a **90-degree clockwise turn** at `(3,2)`, and continues as `(2,1) → (1,0)`. + +**Example 3:** + +**Input:** grid = [[1,2,2,2,2],[2,2,2,2,0],[2,0,0,0,0],[0,0,2,2,2],[2,0,0,2,0]] + +**Output:** 5 + +**Explanation:** + +**![](https://assets.leetcode.com/uploads/2024/12/09/matrix_3.jpg)** + +The longest V-shaped diagonal segment has a length of 5 and follows these coordinates: `(0,0) → (1,1) → (2,2) → (3,3) → (4,4)`. + +**Example 4:** + +**Input:** grid = [[1]] + +**Output:** 1 + +**Explanation:** + +The longest V-shaped diagonal segment has a length of 1 and follows these coordinates: `(0,0)`. + +**Constraints:** + +* `n == grid.length` +* `m == grid[i].length` +* `1 <= n, m <= 500` +* `grid[i][j]` is either `0`, `1` or `2`. \ No newline at end of file diff --git a/src/test/java/g3401_3500/s3451_find_invalid_ip_addresses/MysqlTest.java b/src/test/java/g3401_3500/s3451_find_invalid_ip_addresses/MysqlTest.java new file mode 100644 index 000000000..dc31567fe --- /dev/null +++ b/src/test/java/g3401_3500/s3451_find_invalid_ip_addresses/MysqlTest.java @@ -0,0 +1,70 @@ +package g3401_3500.s3451_find_invalid_ip_addresses; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.stream.Collectors; +import javax.sql.DataSource; +import org.junit.jupiter.api.Test; +import org.zapodot.junit.db.annotations.EmbeddedDatabase; +import org.zapodot.junit.db.annotations.EmbeddedDatabaseTest; +import org.zapodot.junit.db.common.CompatibilityMode; + +@EmbeddedDatabaseTest( + compatibilityMode = CompatibilityMode.MySQL, + initialSqls = + " CREATE TABLE logs (" + + " log_id INT," + + " ip VARCHAR(50)," + + " status_code INT" + + ");" + + "insert into logs (log_id, ip, status_code) values " + + "(1, '192.168.1.1', 200);" + + "insert into logs (log_id, ip, status_code) values " + + "(2, '256.1.2.3', 404);" + + "insert into logs (log_id, ip, status_code) values " + + "(3, '192.168.001.1', 200);" + + "insert into logs (log_id, ip, status_code) values " + + "(4, '192.168.1.1', 200);" + + "insert into logs (log_id, ip, status_code) values " + + "(5, '192.168.1', 500);" + + "insert into logs (log_id, ip, status_code) values " + + "(6, '256.1.2.3', 404);" + + "insert into logs (log_id, ip, status_code) values " + + "(7, '192.168.001.1', 200);") +class MysqlTest { + @Test + void testScript(@EmbeddedDatabase DataSource dataSource) + throws SQLException, FileNotFoundException { + try (final Connection connection = dataSource.getConnection()) { + try (final Statement statement = connection.createStatement(); + final ResultSet resultSet = + statement.executeQuery( + new BufferedReader( + new FileReader( + "src/main/java/g3401_3500/" + + "s3451_find_invalid_ip_addresses/script.sql")) + .lines() + .collect(Collectors.joining("\n")) + .replaceAll("#.*?\\r?\\n", ""))) { + assertThat(resultSet.next(), equalTo(true)); + assertThat(resultSet.getNString(1), equalTo("256.1.2.3")); + assertThat(resultSet.getNString(2), equalTo("2")); + assertThat(resultSet.next(), equalTo(true)); + assertThat(resultSet.getNString(1), equalTo("192.168.001.1")); + assertThat(resultSet.getNString(2), equalTo("2")); + assertThat(resultSet.next(), equalTo(true)); + assertThat(resultSet.getNString(1), equalTo("192.168.1")); + assertThat(resultSet.getNString(2), equalTo("1")); + assertThat(resultSet.next(), equalTo(false)); + } + } + } +} diff --git a/src/test/java/g3401_3500/s3452_sum_of_good_numbers/SolutionTest.java b/src/test/java/g3401_3500/s3452_sum_of_good_numbers/SolutionTest.java new file mode 100644 index 000000000..e70f1b84f --- /dev/null +++ b/src/test/java/g3401_3500/s3452_sum_of_good_numbers/SolutionTest.java @@ -0,0 +1,18 @@ +package g3401_3500.s3452_sum_of_good_numbers; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void sumOfGoodNumbers() { + assertThat(new Solution().sumOfGoodNumbers(new int[] {1, 3, 2, 1, 5, 4}, 2), equalTo(12)); + } + + @Test + void sumOfGoodNumbers2() { + assertThat(new Solution().sumOfGoodNumbers(new int[] {2, 1}, 1), equalTo(2)); + } +} diff --git a/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java b/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java new file mode 100644 index 000000000..c211df0b5 --- /dev/null +++ b/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java @@ -0,0 +1,22 @@ +package g3401_3500.s3453_separate_squares_i; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void separateSquares() { + assertThat( + new Solution().separateSquares(new int[][] {{0, 0, 1}, {2, 2, 1}}), + equalTo(1.0000000012083676D)); + } + + @Test + void separateSquares2() { + assertThat( + new Solution().separateSquares(new int[][] {{0, 0, 2}, {1, 1, 1}}), + equalTo(1.1666666677873083D)); + } +} diff --git a/src/test/java/g3401_3500/s3454_separate_squares_ii/SolutionTest.java b/src/test/java/g3401_3500/s3454_separate_squares_ii/SolutionTest.java new file mode 100644 index 000000000..6d9140e95 --- /dev/null +++ b/src/test/java/g3401_3500/s3454_separate_squares_ii/SolutionTest.java @@ -0,0 +1,20 @@ +package g3401_3500.s3454_separate_squares_ii; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void separateSquares() { + assertThat( + new Solution().separateSquares(new int[][] {{0, 0, 1}, {2, 2, 1}}), equalTo(1.0D)); + } + + @Test + void separateSquares2() { + assertThat( + new Solution().separateSquares(new int[][] {{0, 0, 2}, {1, 1, 1}}), equalTo(1.0D)); + } +} diff --git a/src/test/java/g3401_3500/s3455_shortest_matching_substring/SolutionTest.java b/src/test/java/g3401_3500/s3455_shortest_matching_substring/SolutionTest.java new file mode 100644 index 000000000..55139c1e8 --- /dev/null +++ b/src/test/java/g3401_3500/s3455_shortest_matching_substring/SolutionTest.java @@ -0,0 +1,30 @@ +package g3401_3500.s3455_shortest_matching_substring; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void shortestMatchingSubstring() { + assertThat( + new Solution().shortestMatchingSubstring("abaacbaecebce", "ba*c*ce"), equalTo(8)); + } + + @Test + void shortestMatchingSubstring2() { + assertThat( + new Solution().shortestMatchingSubstring("baccbaadbc", "cc*baa*adb"), equalTo(-1)); + } + + @Test + void shortestMatchingSubstring3() { + assertThat(new Solution().shortestMatchingSubstring("a", "**"), equalTo(0)); + } + + @Test + void shortestMatchingSubstring4() { + assertThat(new Solution().shortestMatchingSubstring("madlogic", "*adlogi*"), equalTo(6)); + } +} diff --git a/src/test/java/g3401_3500/s3456_find_special_substring_of_length_k/SolutionTest.java b/src/test/java/g3401_3500/s3456_find_special_substring_of_length_k/SolutionTest.java new file mode 100644 index 000000000..5c40b70b3 --- /dev/null +++ b/src/test/java/g3401_3500/s3456_find_special_substring_of_length_k/SolutionTest.java @@ -0,0 +1,18 @@ +package g3401_3500.s3456_find_special_substring_of_length_k; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void hasSpecialSubstring() { + assertThat(new Solution().hasSpecialSubstring("aaabaaa", 3), equalTo(true)); + } + + @Test + void hasSpecialSubstring2() { + assertThat(new Solution().hasSpecialSubstring("abc", 2), equalTo(false)); + } +} diff --git a/src/test/java/g3401_3500/s3457_eat_pizzas/SolutionTest.java b/src/test/java/g3401_3500/s3457_eat_pizzas/SolutionTest.java new file mode 100644 index 000000000..6b9b2f3d6 --- /dev/null +++ b/src/test/java/g3401_3500/s3457_eat_pizzas/SolutionTest.java @@ -0,0 +1,18 @@ +package g3401_3500.s3457_eat_pizzas; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void maxWeight() { + assertThat(new Solution().maxWeight(new int[] {1, 2, 3, 4, 5, 6, 7, 8}), equalTo(14L)); + } + + @Test + void maxWeight2() { + assertThat(new Solution().maxWeight(new int[] {2, 1, 1, 1, 1, 1, 1, 1}), equalTo(3L)); + } +} diff --git a/src/test/java/g3401_3500/s3458_select_k_disjoint_special_substrings/SolutionTest.java b/src/test/java/g3401_3500/s3458_select_k_disjoint_special_substrings/SolutionTest.java new file mode 100644 index 000000000..86d92bdf0 --- /dev/null +++ b/src/test/java/g3401_3500/s3458_select_k_disjoint_special_substrings/SolutionTest.java @@ -0,0 +1,23 @@ +package g3401_3500.s3458_select_k_disjoint_special_substrings; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void maxSubstringLength() { + assertThat(new Solution().maxSubstringLength("abcdbaefab", 2), equalTo(true)); + } + + @Test + void maxSubstringLength2() { + assertThat(new Solution().maxSubstringLength("cdefdc", 3), equalTo(false)); + } + + @Test + void maxSubstringLength3() { + assertThat(new Solution().maxSubstringLength("abeabe", 0), equalTo(true)); + } +} diff --git a/src/test/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/SolutionTest.java b/src/test/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/SolutionTest.java new file mode 100644 index 000000000..4b681dd61 --- /dev/null +++ b/src/test/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/SolutionTest.java @@ -0,0 +1,53 @@ +package g3401_3500.s3459_length_of_longest_v_shaped_diagonal_segment; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void lenOfVDiagonal() { + assertThat( + new Solution() + .lenOfVDiagonal( + new int[][] { + {2, 2, 1, 2, 2}, + {2, 0, 2, 2, 0}, + {2, 0, 1, 1, 0}, + {1, 0, 2, 2, 2}, + {2, 0, 0, 2, 2} + }), + equalTo(5)); + } + + @Test + void lenOfVDiagonal2() { + assertThat( + new Solution() + .lenOfVDiagonal( + new int[][] { + {2, 2, 2, 2, 2}, + {2, 0, 2, 2, 0}, + {2, 0, 1, 1, 0}, + {1, 0, 2, 2, 2}, + {2, 0, 0, 2, 2} + }), + equalTo(4)); + } + + @Test + void lenOfVDiagonal3() { + assertThat( + new Solution() + .lenOfVDiagonal( + new int[][] { + {1, 2, 2, 2, 2}, + {2, 2, 2, 2, 0}, + {2, 0, 0, 0, 0}, + {0, 0, 2, 2, 2}, + {2, 0, 0, 2, 0} + }), + equalTo(5)); + } +} From 414febb678f1a0c6c2bf00ab374458bd89377986 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 16 Feb 2025 10:11:41 +0200 Subject: [PATCH 02/11] Fixed sonar --- .../s3454_separate_squares_ii/Solution.java | 97 ++++++++++--------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java index ab0dec617..12f620ce9 100644 --- a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java +++ b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java @@ -1,6 +1,6 @@ package g3401_3500.s3454_separate_squares_ii; -// #Hard #2025_02_16_Time_243_ms_(100.00%)_Space_76.06_MB_(100.00%) +// #Hard #2025_02_16_Time_246_ms_(100.00%)_Space_79.98_MB_(100.00%) import java.util.Arrays; import java.util.Comparator; @@ -9,12 +9,19 @@ public class Solution { public double separateSquares(int[][] squares) { int n = squares.length; int m = 2 * n; + Event[] events = createEvents(squares, m); + double[] xsRaw = createXsRaw(squares, m); + Arrays.sort(events, Comparator.comparingDouble(e -> e.y)); + double[] xs = compress(xsRaw); + double totalUnionArea = calculateTotalUnionArea(events, xs, m); + double target = totalUnionArea / 2.0; + return findSplitPoint(events, xs, m, target); + } + + private Event[] createEvents(int[][] squares, int m) { Event[] events = new Event[m]; - double[] xsRaw = new double[m]; int idx = 0; - int xIdx = 0; for (int[] sq : squares) { - // Each square gives a rectangle [x, x+l] x [y, y+l] double x = sq[0]; double y = sq[1]; double l = sq[2]; @@ -22,43 +29,46 @@ public double separateSquares(int[][] squares) { double y2 = y + l; events[idx++] = new Event(y, x, x2, 1); events[idx++] = new Event(y2, x, x2, -1); + } + return events; + } + + private double[] createXsRaw(int[][] squares, int m) { + double[] xsRaw = new double[m]; + int xIdx = 0; + for (int[] sq : squares) { + double x = sq[0]; + double l = sq[2]; xsRaw[xIdx++] = x; - xsRaw[xIdx++] = x2; + xsRaw[xIdx++] = x + l; } - // Sort events by their y-coordinate (they are exact integers in double format) - Arrays.sort(events, Comparator.comparingDouble(e -> e.y)); - // Compress x-coordinates - double[] xs = compress(xsRaw); - // FIRST SWEEP: compute total union area. + return xsRaw; + } + + private double calculateTotalUnionArea(Event[] events, double[] xs, int m) { SegmentTree segTree = new SegmentTree(xs); double totalUnionArea = 0.0; double lastY = events[0].y; - for (int i = 0; i < m; ) { + int i = 0; + while (i < m) { double curY = events[i].y; if (curY > lastY) { double unionX = segTree.query(); totalUnionArea += unionX * (curY - lastY); lastY = curY; } - // Process all events at y == curY while (i < m && events[i].y == curY) { - int lIdx = Arrays.binarySearch(xs, events[i].x1); - if (lIdx < 0) { - lIdx = -lIdx - 1; - } - int rIdx = Arrays.binarySearch(xs, events[i].x2); - if (rIdx < 0) { - rIdx = -rIdx - 1; - } - segTree.update(1, 0, xs.length - 1, lIdx, rIdx, events[i].type); + int[] indices = findIndices(xs, events[i]); + segTree.update(1, 0, xs.length - 1, indices[0], indices[1], events[i].type); i++; } } - double target = totalUnionArea / 2.0; - // SECOND SWEEP: find minimal y such that cumulative union area reaches target. - // Reinitialize segment tree for a fresh sweep. - segTree = new SegmentTree(xs); - lastY = events[0].y; + return totalUnionArea; + } + + private double findSplitPoint(Event[] events, double[] xs, int m, double target) { + SegmentTree segTree = new SegmentTree(xs); + double lastY = events[0].y; double cumArea = 0.0; for (int i = 0; i < m; ) { double curY = events[i].y; @@ -66,29 +76,32 @@ public double separateSquares(int[][] squares) { double unionX = segTree.query(); double dy = curY - lastY; if (cumArea + unionX * dy >= target - 1e-10) { - // The answer lies in this interval. return lastY + (target - cumArea) / unionX; } cumArea += unionX * dy; lastY = curY; } while (i < m && events[i].y == curY) { - int lIdx = Arrays.binarySearch(xs, events[i].x1); - if (lIdx < 0) { - lIdx = -lIdx - 1; - } - int rIdx = Arrays.binarySearch(xs, events[i].x2); - if (rIdx < 0) { - rIdx = -rIdx - 1; - } - segTree.update(1, 0, xs.length - 1, lIdx, rIdx, events[i].type); + int[] indices = findIndices(xs, events[i]); + segTree.update(1, 0, xs.length - 1, indices[0], indices[1], events[i].type); i++; } } return lastY; } - // Compress an array of doubles into a sorted array of unique values. + private int[] findIndices(double[] xs, Event event) { + int lIdx = Arrays.binarySearch(xs, event.x1); + if (lIdx < 0) { + lIdx = -lIdx - 1; + } + int rIdx = Arrays.binarySearch(xs, event.x2); + if (rIdx < 0) { + rIdx = -rIdx - 1; + } + return new int[] {lIdx, rIdx}; + } + private double[] compress(double[] arr) { Arrays.sort(arr); int cnt = 1; @@ -108,12 +121,10 @@ private double[] compress(double[] arr) { return res; } - // Event class for the sweep-line. private static class Event { double y; double x1; double x2; - // +1 for adding an interval; -1 for removing. int type; Event(double y, double x1, double x2, int type) { @@ -124,26 +135,19 @@ private static class Event { } } - // Segment Tree for maintaining the union length over the x-axis. private static class SegmentTree { int n; - // Covered length of the segment. double[] tree; - // Coverage count for the segment. int[] count; - // The compressed x-coordinates. double[] xs; SegmentTree(double[] xs) { this.xs = xs; this.n = xs.length; - // Allocate 4*n size arrays. tree = new double[4 * n]; count = new int[4 * n]; } - // Update the range [ql, qr) with value 'val'. - // The current node covers indices [l, r) in xs. void update(int idx, int l, int r, int ql, int qr, int val) { if (qr <= l || ql >= r) { return; @@ -164,7 +168,6 @@ void update(int idx, int l, int r, int ql, int qr, int val) { } } - // Query the current total union length. double query() { return tree[1]; } From 49f7f027c58beece4665940ea2001d2fee22a541 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 16 Feb 2025 20:58:45 +0200 Subject: [PATCH 03/11] Fixed sonar --- .../s3452_sum_of_good_numbers/Solution.java | 12 ++---- .../s3454_separate_squares_ii/Solution.java | 3 +- .../Solution.java | 1 + .../Solution.java | 39 +++++++++++++++---- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java b/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java index 02a47f034..54be92e72 100644 --- a/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java +++ b/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java @@ -8,15 +8,11 @@ public int sumOfGoodNumbers(int[] nums, int k) { int n = nums.length; for (int i = 0; i < n; i++) { boolean isGood = true; - if (i - k >= 0) { - if (nums[i] <= nums[i - k]) { - isGood = false; - } + if (i - k >= 0 && nums[i] <= nums[i - k]) { + isGood = false; } - if (i + k < n) { - if (nums[i] <= nums[i + k]) { - isGood = false; - } + if (i + k < n && nums[i] <= nums[i + k]) { + isGood = false; } if (isGood) { totalSum += nums[i]; diff --git a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java index 12f620ce9..8452da2d6 100644 --- a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java +++ b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java @@ -70,7 +70,8 @@ private double findSplitPoint(Event[] events, double[] xs, int m, double target) SegmentTree segTree = new SegmentTree(xs); double lastY = events[0].y; double cumArea = 0.0; - for (int i = 0; i < m; ) { + int i = 0; + while (i < m) { double curY = events[i].y; if (curY > lastY) { double unionX = segTree.query(); diff --git a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java index 0ab193ada..81475f40d 100644 --- a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java +++ b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java @@ -2,6 +2,7 @@ // #Hard #2025_02_16_Time_976_ms_(100.00%)_Space_45.76_MB_(100.00%) +@SuppressWarnings("java:S6541") public class Solution { public int shortestMatchingSubstring(String s, String p) { int minLen = Integer.MAX_VALUE; diff --git a/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java b/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java index 80f269bb0..1998dafbe 100644 --- a/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java +++ b/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java @@ -5,9 +5,7 @@ import java.util.Arrays; public class Solution { - public boolean maxSubstringLength(String s, int k) { - char[] arr = s.toCharArray(); - int n = arr.length; + private int[][] buildFrequencyArray(char[] arr, int n) { int[][] freq = new int[2][26]; for (int[] is : freq) { Arrays.fill(is, -1); @@ -19,6 +17,10 @@ public boolean maxSubstringLength(String s, int k) { } freq[1][x] = i; } + return freq; + } + + private void updateFrequencyBounds(int[][] freq, char[] arr) { for (int i = 0; i < 26; i++) { if (freq[0][i] == -1) { continue; @@ -32,6 +34,9 @@ public boolean maxSubstringLength(String s, int k) { freq[1][i] = max; freq[0][i] = min; } + } + + private int[][] buildTempArray(int[][] freq) { int[][] temp = new int[2][26]; int x = 0; for (int i = 0; i < 26; i++) { @@ -44,11 +49,10 @@ public boolean maxSubstringLength(String s, int k) { x++; } } - int[][] nums = new int[x][2]; - for (int i = 0; i < x; i++) { - nums[i][0] = temp[0][i]; - nums[i][1] = temp[1][i]; - } + return new int[][] {temp[0], temp[1], new int[] {x}}; + } + + private int[][] processIntervals(int[][] nums, int x) { Arrays.sort(nums, (a, b) -> a[0] - b[0]); int[][] ans = new int[x][2]; int y = 0; @@ -71,6 +75,25 @@ public boolean maxSubstringLength(String s, int k) { } } } + return new int[][] {ans[0], new int[] {y}}; + } + + public boolean maxSubstringLength(String s, int k) { + char[] arr = s.toCharArray(); + int n = arr.length; + int[][] freq = buildFrequencyArray(arr, n); + updateFrequencyBounds(freq, arr); + int[][] tempResult = buildTempArray(freq); + int[][] temp = new int[][] {tempResult[0], tempResult[1]}; + int x = tempResult[2][0]; + int[][] nums = new int[x][2]; + for (int i = 0; i < x; i++) { + nums[i][0] = temp[0][i]; + nums[i][1] = temp[1][i]; + } + int[][] processedResult = processIntervals(nums, x); + int[][] ans = new int[][] {processedResult[0]}; + int y = processedResult[1][0]; if (y >= k) { if (y == 1 && k == 1) { return ans[0][0] != 0 || ans[0][1] != n - 1; From 4d6547b5cfac838f0c6b33b082edaddeda1546c9 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 16 Feb 2025 22:15:56 +0200 Subject: [PATCH 04/11] Improved 3455 --- .../Solution.java | 145 ++++++++++-------- 1 file changed, 80 insertions(+), 65 deletions(-) diff --git a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java index 81475f40d..943262791 100644 --- a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java +++ b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java @@ -1,80 +1,95 @@ package g3401_3500.s3455_shortest_matching_substring; -// #Hard #2025_02_16_Time_976_ms_(100.00%)_Space_45.76_MB_(100.00%) +// #Hard #2025_02_16_Time_91_ms_(100.00%)_Space_55.37_MB_(100.00%) + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; -@SuppressWarnings("java:S6541") public class Solution { + private List getMatch(String s, String p) { + int n = s.length(); + int m = p.length(); + int[] next = new int[m]; + Arrays.fill(next, -1); + for (int i = 1, j = -1; i < m; ++i) { + while (j != -1 && p.charAt(i) != p.charAt(j + 1)) { + j = next[j]; + } + if (p.charAt(i) == p.charAt(j + 1)) { + ++j; + } + next[i] = j; + } + List match = new ArrayList<>(); + for (int i = 0, j = -1; i < n; ++i) { + while (j != -1 && s.charAt(i) != p.charAt(j + 1)) { + j = next[j]; + } + if (s.charAt(i) == p.charAt(j + 1)) { + ++j; + } + if (j == m - 1) { + match.add(i - m + 1); + j = next[j]; + } + } + return match; + } + public int shortestMatchingSubstring(String s, String p) { - int minLen = Integer.MAX_VALUE; - String[] ar = p.split("\\*"); - int arlen = ar.length; - if (arlen == 0) { + int n = s.length(); + int m = p.length(); + int[] d = {-1, -1, -1, m}; + for (int i = 0; i < m; ++i) { + if (p.charAt(i) == '*') { + d[d[1] == -1 ? 1 : 2] = i; + } + } + List subs = new ArrayList<>(); + for (int i = 0; i < 3; ++i) { + if (d[i] + 1 < d[i + 1]) { + subs.add(p.substring(d[i] + 1, d[i + 1])); + } + } + int size = subs.size(); + if (size == 0) { return 0; } - String temp = p.replace("*", ""); - if (s.contains(temp)) { - return temp.length(); + List> matches = new ArrayList<>(); + for (String sub : subs) { + matches.add(getMatch(s, sub)); } - int f = s.indexOf(ar[0]); - while (f != -1) { - int shortLen = Integer.MAX_VALUE; - if (arlen > 1) { - int sec = s.indexOf(ar[1], f + ar[0].length()); - while (sec != -1) { - if (ar[0].isEmpty()) { - f = sec; - } - if (arlen > 2) { - int third = s.indexOf(ar[2], sec + ar[1].length()); - if (third != -1) { - if (ar[0].isEmpty() && ar[1].isEmpty()) { - f = third; - } - shortLen = third + ar[2].length() - f; - minLen = Math.min(shortLen, minLen); - if (minLen == p.length() - 2) { - return minLen; - } - if (minLen == Integer.MAX_VALUE) { - return -1; - } - } - } else { - shortLen = sec + ar[1].length() - f; - minLen = Math.min(shortLen, minLen); - } - if (minLen == p.length() - 2) { - return minLen; - } - if (ar[1].isEmpty()) { - sec = -1; - } else { - sec = s.indexOf(ar[1], sec + 1); - } - if (minLen == Integer.MAX_VALUE) { - return -1; - } + int ans = Integer.MAX_VALUE; + int[] ids = new int[size]; + Arrays.fill(ids, 0); + while (ids[size - 1] < matches.get(size - 1).size()) { + for (int i = size - 2; i >= 0; --i) { + while (ids[i] + 1 < matches.get(i).size() + && matches.get(i).get(ids[i] + 1) + subs.get(i).length() + <= matches.get(i + 1).get(ids[i + 1])) { + ++ids[i]; } - } else { - shortLen = f + ar[0].length() - f; - minLen = shortLen; - } - minLen = Math.min(shortLen, minLen); - if (minLen == p.length() - 2) { - return minLen; } - if (ar[0].isEmpty()) { - f = -1; - } else { - f = s.indexOf(ar[0], f + 1); + boolean valid = true; + for (int i = size - 2; i >= 0; --i) { + if (ids[i] >= matches.get(i).size() + || matches.get(i).get(ids[i]) + subs.get(i).length() + > matches.get(i + 1).get(ids[i + 1])) { + valid = false; + break; + } } - if (minLen == Integer.MAX_VALUE) { - return -1; + if (valid) { + ans = + Math.min( + ans, + matches.get(size - 1).get(ids[size - 1]) + + subs.get(size - 1).length() + - matches.get(0).get(ids[0])); } + ids[size - 1]++; } - if (minLen == Integer.MAX_VALUE) { - return -1; - } - return minLen; + return ans > n ? -1 : ans; } } From b2009a8b254588f8db0a3f90c9a876c52e66028f Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 16 Feb 2025 22:19:20 +0200 Subject: [PATCH 05/11] Improved 3456 --- .../Solution.java | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java index 3457210a6..85afe0b22 100644 --- a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java +++ b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java @@ -1,36 +1,45 @@ package g3401_3500.s3456_find_special_substring_of_length_k; -// #Easy #2025_02_16_Time_1_ms_(100.00%)_Space_42.04_MB_(100.00%) +// #Easy #2025_02_16_Time_0_ms_(100.00%)_Space_42.05_MB_(100.00%) public class Solution { public boolean hasSpecialSubstring(String s, int k) { - // 🚫 If string is smaller than k, no valid substring exists - if (s.length() < k) { - return false; + if (s.length() == k) { + if (k == 1) { + return true; + } + for (int i = 0; i < k - 1; i++) { + if (s.charAt(i) != s.charAt(i + 1)) { + return false; + } + } + return true; } - // 🔍 Iterate through all possible substrings of length k - for (int i = 0; i <= s.length() - k; i++) { - // 🧮 Count consecutive identical characters - int count = 1; - // ✅ Check if all k characters in the substring are the same - for (int j = i; j < i + k - 1; j++) { - if (s.charAt(j) == s.charAt(j + 1)) { - // ➕ Increase count if consecutive characters are the same - count++; - } else { - // ❌ Break if mismatch occurs + int start = 0; + int end = k; + while (end <= s.length()) { + boolean flag = false; + for (int i = start; i < end - 1; i++) { + if (s.charAt(i) != s.charAt(i + 1)) { + start++; + end++; + flag = true; break; } } - // 🔎 Ensure the substring is not part of a larger group - if (count == k - && (i == 0 || s.charAt(i - 1) != s.charAt(i)) - && (i + k == s.length() || s.charAt(i + k) != s.charAt(i))) { - // 🎯 Found a valid special substring + if (flag) { + continue; + } + if (start - 1 >= 0 && s.charAt(start) == s.charAt(start - 1)) { + start++; + end++; + } else if (end < s.length() && s.charAt(end) == s.charAt(end - 1)) { + start++; + end++; + } else { return true; } } - // ❌ No valid substring found return false; } } From 2307542893cd9fbe014c226533805cf239ff5b2e Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 16 Feb 2025 22:28:14 +0200 Subject: [PATCH 06/11] Fixed sonar --- .../s3455_shortest_matching_substring/Solution.java | 10 ++++++++-- .../Solution.java | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java index 943262791..8d0cd99f9 100644 --- a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java +++ b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java @@ -12,7 +12,9 @@ private List getMatch(String s, String p) { int m = p.length(); int[] next = new int[m]; Arrays.fill(next, -1); - for (int i = 1, j = -1; i < m; ++i) { + int i = 1; + int j = -1; + while (i < m) { while (j != -1 && p.charAt(i) != p.charAt(j + 1)) { j = next[j]; } @@ -20,9 +22,12 @@ private List getMatch(String s, String p) { ++j; } next[i] = j; + ++i; } List match = new ArrayList<>(); - for (int i = 0, j = -1; i < n; ++i) { + i = 0; + j = -1; + while (i < n) { while (j != -1 && s.charAt(i) != p.charAt(j + 1)) { j = next[j]; } @@ -33,6 +38,7 @@ private List getMatch(String s, String p) { match.add(i - m + 1); j = next[j]; } + ++i; } return match; } diff --git a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java index 85afe0b22..66d397bd4 100644 --- a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java +++ b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java @@ -2,6 +2,7 @@ // #Easy #2025_02_16_Time_0_ms_(100.00%)_Space_42.05_MB_(100.00%) +@SuppressWarnings("java:S1871") public class Solution { public boolean hasSpecialSubstring(String s, int k) { if (s.length() == k) { From e99ac35069941cc424d0117e5436f9620fe30a9e Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sun, 16 Feb 2025 22:30:09 +0200 Subject: [PATCH 07/11] Fixed sonar --- .../Solution.java | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java index 66d397bd4..150ee5e05 100644 --- a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java +++ b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java @@ -1,21 +1,10 @@ package g3401_3500.s3456_find_special_substring_of_length_k; -// #Easy #2025_02_16_Time_0_ms_(100.00%)_Space_42.05_MB_(100.00%) +// #Easy #2025_02_16_Time_1_ms_(100.00%)_Space_42.25_MB_(100.00%) @SuppressWarnings("java:S1871") public class Solution { public boolean hasSpecialSubstring(String s, int k) { - if (s.length() == k) { - if (k == 1) { - return true; - } - for (int i = 0; i < k - 1; i++) { - if (s.charAt(i) != s.charAt(i + 1)) { - return false; - } - } - return true; - } int start = 0; int end = k; while (end <= s.length()) { From de9eb239f043890c95633d0d76343057337ef2cc Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 18 Feb 2025 08:12:24 +0200 Subject: [PATCH 08/11] Improved tags --- .../script.sql | 2 +- .../s3452_sum_of_good_numbers/Solution.java | 7 +- .../s3453_separate_squares_i/Solution.java | 52 ++-- .../s3454_separate_squares_ii/Solution.java | 254 ++++++++---------- .../Solution.java | 3 +- .../Solution.java | 2 +- .../g3401_3500/s3457_eat_pizzas/Solution.java | 2 +- .../Solution.java | 125 +++------ .../Solution.java | 3 +- 9 files changed, 186 insertions(+), 264 deletions(-) diff --git a/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/script.sql b/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/script.sql index 77e206f5d..7aac57611 100644 --- a/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/script.sql +++ b/src/main/java/g3401_3500/s3451_find_invalid_ip_addresses/script.sql @@ -1,5 +1,5 @@ # Write your MySQL query statement below -# #Hard #2025_02_16_Time_383_ms_(85.47%)_Space_0.0_MB_(100.00%) +# #Hard #Database #2025_02_18_Time_393_ms_(79.56%)_Space_0.0_MB_(100.00%) WITH cte_invalid_ip AS ( SELECT log_id, ip FROM logs diff --git a/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java b/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java index 54be92e72..e8ca20098 100644 --- a/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java +++ b/src/main/java/g3401_3500/s3452_sum_of_good_numbers/Solution.java @@ -1,16 +1,13 @@ package g3401_3500.s3452_sum_of_good_numbers; -// #Easy #2025_02_16_Time_1_ms_(100.00%)_Space_44.30_MB_(100.00%) +// #Easy #Array #2025_02_18_Time_1_ms_(99.99%)_Space_44.75_MB_(7.31%) public class Solution { public int sumOfGoodNumbers(int[] nums, int k) { int totalSum = 0; int n = nums.length; for (int i = 0; i < n; i++) { - boolean isGood = true; - if (i - k >= 0 && nums[i] <= nums[i - k]) { - isGood = false; - } + boolean isGood = i - k < 0 || nums[i] > nums[i - k]; if (i + k < n && nums[i] <= nums[i + k]) { isGood = false; } diff --git a/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java b/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java index 81aa081d2..fef0c84fb 100644 --- a/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java +++ b/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java @@ -1,42 +1,34 @@ package g3401_3500.s3453_separate_squares_i; -// #Medium #2025_02_16_Time_123_ms_(100.00%)_Space_87.97_MB_(_%) +// #Medium #Array #Binary_Search #2025_02_18_Time_60_ms_(99.96%)_Space_88.58_MB_(26.92%) public class Solution { - private double helper(double line, int[][] squares) { - double aAbove = 0; - double aBelow = 0; - for (int[] square : squares) { - int y = square[1]; - int l = square[2]; - double total = (double) l * l; - if (line <= y) { - aAbove += total; - } else if (line >= y + l) { - aBelow += total; + public double separateSquares(int[][] squares) { + long hi = 0L; + long lo = 1_000_000_000L; + for (int[] q : squares) { + lo = Math.min(lo, q[1]); + hi = Math.max(hi, q[1] + q[2]); + } + while (lo <= hi) { + long mid = (lo + hi) / 2; + if (diff(mid, squares) <= 0) { + hi = mid - 1; } else { - // The line intersects the square. - double aboveHeight = (y + l) - line; - double belowHeight = line - y; - aAbove += l * aboveHeight; - aBelow += l * belowHeight; + lo = mid + 1; } } - return aAbove - aBelow; + double diff1 = diff(hi, squares); + double diff2 = diff(lo, squares); + return (double) hi + diff1 / (diff1 - diff2); } - public double separateSquares(int[][] squares) { - double lo = 0; - double hi = 2 * 1e9; - for (int i = 0; i < 60; i++) { - double mid = (lo + hi) / 2.0; - double diff = helper(mid, squares); - if (diff > 0) { - lo = mid; - } else { - hi = mid; - } + private double diff(long mid, int[][] squares) { + double[] res = new double[2]; + for (int[] q : squares) { + res[0] += Math.min(q[2], Math.max(0, mid - q[1])) * q[2]; + res[1] += Math.min(q[2], Math.max(0, q[1] + q[2] - mid)) * q[2]; } - return hi; + return res[1] - res[0]; } } diff --git a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java index 8452da2d6..557d2f463 100644 --- a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java +++ b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java @@ -1,176 +1,154 @@ package g3401_3500.s3454_separate_squares_ii; -// #Hard #2025_02_16_Time_246_ms_(100.00%)_Space_79.98_MB_(100.00%) +// #Hard #Array #Binary_Search #Segment_Tree #Line_Sweep +// #2025_02_18_Time_156_ms_(80.18%)_Space_79.96_MB_(64.32%) +import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; +import java.util.List; public class Solution { - public double separateSquares(int[][] squares) { - int n = squares.length; - int m = 2 * n; - Event[] events = createEvents(squares, m); - double[] xsRaw = createXsRaw(squares, m); - Arrays.sort(events, Comparator.comparingDouble(e -> e.y)); - double[] xs = compress(xsRaw); - double totalUnionArea = calculateTotalUnionArea(events, xs, m); - double target = totalUnionArea / 2.0; - return findSplitPoint(events, xs, m, target); - } - - private Event[] createEvents(int[][] squares, int m) { - Event[] events = new Event[m]; - int idx = 0; - for (int[] sq : squares) { - double x = sq[0]; - double y = sq[1]; - double l = sq[2]; - double x2 = x + l; - double y2 = y + l; - events[idx++] = new Event(y, x, x2, 1); - events[idx++] = new Event(y2, x, x2, -1); - } - return events; - } - - private double[] createXsRaw(int[][] squares, int m) { - double[] xsRaw = new double[m]; - int xIdx = 0; - for (int[] sq : squares) { - double x = sq[0]; - double l = sq[2]; - xsRaw[xIdx++] = x; - xsRaw[xIdx++] = x + l; - } - return xsRaw; - } - - private double calculateTotalUnionArea(Event[] events, double[] xs, int m) { - SegmentTree segTree = new SegmentTree(xs); - double totalUnionArea = 0.0; - double lastY = events[0].y; - int i = 0; - while (i < m) { - double curY = events[i].y; - if (curY > lastY) { - double unionX = segTree.query(); - totalUnionArea += unionX * (curY - lastY); - lastY = curY; - } - while (i < m && events[i].y == curY) { - int[] indices = findIndices(xs, events[i]); - segTree.update(1, 0, xs.length - 1, indices[0], indices[1], events[i].type); - i++; - } - } - return totalUnionArea; - } - - private double findSplitPoint(Event[] events, double[] xs, int m, double target) { - SegmentTree segTree = new SegmentTree(xs); - double lastY = events[0].y; - double cumArea = 0.0; - int i = 0; - while (i < m) { - double curY = events[i].y; - if (curY > lastY) { - double unionX = segTree.query(); - double dy = curY - lastY; - if (cumArea + unionX * dy >= target - 1e-10) { - return lastY + (target - cumArea) / unionX; - } - cumArea += unionX * dy; - lastY = curY; - } - while (i < m && events[i].y == curY) { - int[] indices = findIndices(xs, events[i]); - segTree.update(1, 0, xs.length - 1, indices[0], indices[1], events[i].type); - i++; - } - } - return lastY; - } - - private int[] findIndices(double[] xs, Event event) { - int lIdx = Arrays.binarySearch(xs, event.x1); - if (lIdx < 0) { - lIdx = -lIdx - 1; - } - int rIdx = Arrays.binarySearch(xs, event.x2); - if (rIdx < 0) { - rIdx = -rIdx - 1; - } - return new int[] {lIdx, rIdx}; - } - - private double[] compress(double[] arr) { - Arrays.sort(arr); - int cnt = 1; - for (int i = 1; i < arr.length; i++) { - if (arr[i] != arr[i - 1]) { - cnt++; - } - } - double[] res = new double[cnt]; - res[0] = arr[0]; - int j = 1; - for (int i = 1; i < arr.length; i++) { - if (arr[i] != arr[i - 1]) { - res[j++] = arr[i]; - } - } - return res; - } - - private static class Event { + private static class Event implements Comparable { double y; - double x1; - double x2; + int x1; + int x2; int type; - Event(double y, double x1, double x2, int type) { + Event(double y, int x1, int x2, int type) { this.y = y; this.x1 = x1; this.x2 = x2; this.type = type; } + + public int compareTo(Event other) { + return Double.compare(this.y, other.y); + } + } + + private static class Segment { + double y1; + double y2; + double unionX; + double cumArea; + + Segment(double y1, double y2, double unionX, double cumArea) { + this.y1 = y1; + this.y2 = y2; + this.unionX = unionX; + this.cumArea = cumArea; + } } private static class SegmentTree { - int n; - double[] tree; int[] count; - double[] xs; + double[] len; + int n; + int[] x; - SegmentTree(double[] xs) { - this.xs = xs; - this.n = xs.length; - tree = new double[4 * n]; + SegmentTree(int[] x) { + this.x = x; + n = x.length - 1; count = new int[4 * n]; + len = new double[4 * n]; } void update(int idx, int l, int r, int ql, int qr, int val) { - if (qr <= l || ql >= r) { + if (qr < l || ql > r) { return; } if (ql <= l && r <= qr) { count[idx] += val; } else { - int mid = (l + r) >> 1; - update(idx << 1, l, mid, ql, qr, val); - update(idx << 1 | 1, mid, r, ql, qr, val); + int mid = (l + r) / 2; + update(2 * idx + 1, l, mid, ql, qr, val); + update(2 * idx + 2, mid + 1, r, ql, qr, val); } if (count[idx] > 0) { - tree[idx] = xs[r] - xs[l]; - } else if (r - l == 1) { - tree[idx] = 0; + len[idx] = x[r + 1] - x[l]; } else { - tree[idx] = tree[idx << 1] + tree[idx << 1 | 1]; + if (l == r) { + len[idx] = 0; + } else { + len[idx] = len[2 * idx + 1] + len[2 * idx + 2]; + } } } + void update(int ql, int qr, int val) { + update(0, 0, n - 1, ql, qr, val); + } + double query() { - return tree[1]; + return len[0]; + } + } + + public double separateSquares(int[][] squares) { + int n = squares.length; + Event[] events = new Event[2 * n]; + int idx = 0; + List xList = new ArrayList<>(); + for (int[] s : squares) { + int x = s[0]; + int y = s[1]; + int l = s[2]; + int x2 = x + l; + int y2 = y + l; + events[idx++] = new Event(y, x, x2, 1); + events[idx++] = new Event(y2, x, x2, -1); + xList.add(x); + xList.add(x2); + } + Arrays.sort(events); + int m = xList.size(); + int[] xCords = new int[m]; + for (int i = 0; i < m; i++) { + xCords[i] = xList.get(i); + } + Arrays.sort(xCords); + int uniqueCount = 0; + for (int i = 0; i < m; i++) { + if (i == 0 || xCords[i] != xCords[i - 1]) { + xCords[uniqueCount++] = xCords[i]; + } + } + int[] x = Arrays.copyOf(xCords, uniqueCount); + SegmentTree segTree = new SegmentTree(x); + List segments = new ArrayList<>(); + double cumArea = 0.0; + double lastY = events[0].y; + int iEvent = 0; + while (iEvent < events.length) { + double currentY = events[iEvent].y; + double delta = currentY - lastY; + if (delta > 0) { + double unionX = segTree.query(); + segments.add(new Segment(lastY, currentY, unionX, cumArea)); + cumArea += unionX * delta; + } + while (iEvent < events.length && events[iEvent].y == currentY) { + Event e = events[iEvent]; + int left = Arrays.binarySearch(x, e.x1); + int right = Arrays.binarySearch(x, e.x2); + if (left < right) { + segTree.update(left, right - 1, e.type); + } + iEvent++; + } + lastY = currentY; + } + double totalArea = cumArea; + double target = totalArea / 2.0; + double answer; + for (Segment seg : segments) { + double segArea = seg.unionX * (seg.y2 - seg.y1); + if (seg.cumArea + segArea >= target) { + double needed = target - seg.cumArea; + answer = seg.y1 + needed / seg.unionX; + return answer; + } } + return lastY; } } diff --git a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java index 8d0cd99f9..23b36f95f 100644 --- a/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java +++ b/src/main/java/g3401_3500/s3455_shortest_matching_substring/Solution.java @@ -1,6 +1,7 @@ package g3401_3500.s3455_shortest_matching_substring; -// #Hard #2025_02_16_Time_91_ms_(100.00%)_Space_55.37_MB_(100.00%) +// #Hard #String #Binary_Search #Two_Pointers #String_Matching +// #2025_02_18_Time_116_ms_(81.44%)_Space_55.28_MB_(88.02%) import java.util.ArrayList; import java.util.Arrays; diff --git a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java index 150ee5e05..449b739b2 100644 --- a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java +++ b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java @@ -1,6 +1,6 @@ package g3401_3500.s3456_find_special_substring_of_length_k; -// #Easy #2025_02_16_Time_1_ms_(100.00%)_Space_42.25_MB_(100.00%) +// #Easy #String #2025_02_18_Time_0_ms_(100.00%)_Space_41.93_MB_(99.07%) @SuppressWarnings("java:S1871") public class Solution { diff --git a/src/main/java/g3401_3500/s3457_eat_pizzas/Solution.java b/src/main/java/g3401_3500/s3457_eat_pizzas/Solution.java index 696b35b08..de35a7396 100644 --- a/src/main/java/g3401_3500/s3457_eat_pizzas/Solution.java +++ b/src/main/java/g3401_3500/s3457_eat_pizzas/Solution.java @@ -1,6 +1,6 @@ package g3401_3500.s3457_eat_pizzas; -// #Medium #2025_02_16_Time_64_ms_(100.00%)_Space_80.85_MB_(100.00%) +// #Medium #Array #Sorting #Greedy #2025_02_18_Time_63_ms_(40.14%)_Space_81.02_MB_(36.94%) import java.util.Arrays; diff --git a/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java b/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java index 1998dafbe..7af2bd875 100644 --- a/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java +++ b/src/main/java/g3401_3500/s3458_select_k_disjoint_special_substrings/Solution.java @@ -1,105 +1,58 @@ package g3401_3500.s3458_select_k_disjoint_special_substrings; -// #Medium #2025_02_16_Time_21_ms_(100.00%)_Space_45.30_MB_(100.00%) +// #Medium #String #Hash_Table #Dynamic_Programming #Sorting #Greedy +// #2025_02_18_Time_7_ms_(95.31%)_Space_45.21_MB_(87.79%) +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; public class Solution { - private int[][] buildFrequencyArray(char[] arr, int n) { - int[][] freq = new int[2][26]; - for (int[] is : freq) { - Arrays.fill(is, -1); + public boolean maxSubstringLength(String s, int k) { + int n = s.length(); + if (k == 0) { + return true; } + int[] first = new int[26]; + int[] last = new int[26]; + Arrays.fill(first, n); + Arrays.fill(last, -1); for (int i = 0; i < n; i++) { - int x = arr[i] - 97; - if (freq[0][x] == -1) { - freq[0][x] = i; - } - freq[1][x] = i; + int c = s.charAt(i) - 'a'; + first[c] = Math.min(first[c], i); + last[c] = i; } - return freq; - } - - private void updateFrequencyBounds(int[][] freq, char[] arr) { - for (int i = 0; i < 26; i++) { - if (freq[0][i] == -1) { + List intervals = new ArrayList<>(); + for (int c = 0; c < 26; c++) { + if (last[c] == -1) { continue; } - int max = freq[1][i]; - int min = freq[0][i]; - for (int j = freq[0][i]; j <= freq[1][i]; j++) { - max = Math.max(max, freq[1][arr[j] - 'a']); - min = Math.min(min, freq[0][arr[j] - 'a']); - } - freq[1][i] = max; - freq[0][i] = min; - } - } - - private int[][] buildTempArray(int[][] freq) { - int[][] temp = new int[2][26]; - int x = 0; - for (int i = 0; i < 26; i++) { - if (freq[0][i] != -1) { - temp[0][x] = freq[0][i]; - temp[1][x] = freq[1][i]; - if (temp[1][x] == -1) { - temp[1][x] = temp[0][x]; + int start = first[c]; + int end = last[c]; + int j = start; + boolean valid = true; + while (j <= end) { + int cur = s.charAt(j) - 'a'; + if (first[cur] < start) { + valid = false; + break; } - x++; + end = Math.max(end, last[cur]); + j++; } - } - return new int[][] {temp[0], temp[1], new int[] {x}}; - } - - private int[][] processIntervals(int[][] nums, int x) { - Arrays.sort(nums, (a, b) -> a[0] - b[0]); - int[][] ans = new int[x][2]; - int y = 0; - for (int i = 0; i < x; i++) { - if (y == 0) { - ans[y][0] = nums[i][0]; - ans[y][1] = nums[i][1]; - y++; - } else { - if (ans[y - 1][1] > nums[i][0]) { - if (ans[y - 1][1] < nums[i][1]) { - continue; - } - ans[y - 1][0] = nums[i][0]; - ans[y - 1][1] = nums[i][1]; - } else { - ans[y][0] = nums[i][0]; - ans[y][1] = nums[i][1]; - y++; - } + if (valid && !(start == 0 && end == n - 1)) { + intervals.add(new int[] {start, end}); } } - return new int[][] {ans[0], new int[] {y}}; - } - - public boolean maxSubstringLength(String s, int k) { - char[] arr = s.toCharArray(); - int n = arr.length; - int[][] freq = buildFrequencyArray(arr, n); - updateFrequencyBounds(freq, arr); - int[][] tempResult = buildTempArray(freq); - int[][] temp = new int[][] {tempResult[0], tempResult[1]}; - int x = tempResult[2][0]; - int[][] nums = new int[x][2]; - for (int i = 0; i < x; i++) { - nums[i][0] = temp[0][i]; - nums[i][1] = temp[1][i]; - } - int[][] processedResult = processIntervals(nums, x); - int[][] ans = new int[][] {processedResult[0]}; - int y = processedResult[1][0]; - if (y >= k) { - if (y == 1 && k == 1) { - return ans[0][0] != 0 || ans[0][1] != n - 1; + intervals.sort((a, b) -> Integer.compare(a[1], b[1])); + int count = 0; + int prevEnd = -1; + for (int[] interval : intervals) { + if (interval[0] > prevEnd) { + count++; + prevEnd = interval[1]; } - return true; } - return false; + return count >= k; } } diff --git a/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/Solution.java b/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/Solution.java index f370c6032..013814405 100644 --- a/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/Solution.java +++ b/src/main/java/g3401_3500/s3459_length_of_longest_v_shaped_diagonal_segment/Solution.java @@ -1,6 +1,7 @@ package g3401_3500.s3459_length_of_longest_v_shaped_diagonal_segment; -// #Hard #2025_02_16_Time_484_ms_(100.00%)_Space_139.26_MB_(_%) +// #Hard #Array #Dynamic_Programming #Matrix #Memoization +// #2025_02_18_Time_461_ms_(36.09%)_Space_127.47_MB_(39.48%) import java.util.Arrays; From e8797d0f6210e85df8660e66d860ea23ac18ed03 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 18 Feb 2025 08:16:05 +0200 Subject: [PATCH 09/11] Fixed test --- .../g3401_3500/s3453_separate_squares_i/SolutionTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java b/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java index c211df0b5..0fa863aa9 100644 --- a/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java +++ b/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java @@ -10,13 +10,13 @@ class SolutionTest { void separateSquares() { assertThat( new Solution().separateSquares(new int[][] {{0, 0, 1}, {2, 2, 1}}), - equalTo(1.0000000012083676D)); + equalTo(1.0)); } @Test void separateSquares2() { assertThat( new Solution().separateSquares(new int[][] {{0, 0, 2}, {1, 1, 1}}), - equalTo(1.1666666677873083D)); + equalTo(1.1666666666666667)); } } From febae71e0d36918c07e82e84dbb1ac27e9361da3 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 18 Feb 2025 08:18:34 +0200 Subject: [PATCH 10/11] Fixed test --- .../s3456_find_special_substring_of_length_k/Solution.java | 6 ++---- .../g3401_3500/s3453_separate_squares_i/SolutionTest.java | 3 +-- .../SolutionTest.java | 5 +++++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java index 449b739b2..b49eda195 100644 --- a/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java +++ b/src/main/java/g3401_3500/s3456_find_special_substring_of_length_k/Solution.java @@ -20,10 +20,8 @@ public boolean hasSpecialSubstring(String s, int k) { if (flag) { continue; } - if (start - 1 >= 0 && s.charAt(start) == s.charAt(start - 1)) { - start++; - end++; - } else if (end < s.length() && s.charAt(end) == s.charAt(end - 1)) { + if (start - 1 >= 0 && s.charAt(start) == s.charAt(start - 1) + || end < s.length() && s.charAt(end) == s.charAt(end - 1)) { start++; end++; } else { diff --git a/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java b/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java index 0fa863aa9..cd65874ce 100644 --- a/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java +++ b/src/test/java/g3401_3500/s3453_separate_squares_i/SolutionTest.java @@ -9,8 +9,7 @@ class SolutionTest { @Test void separateSquares() { assertThat( - new Solution().separateSquares(new int[][] {{0, 0, 1}, {2, 2, 1}}), - equalTo(1.0)); + new Solution().separateSquares(new int[][] {{0, 0, 1}, {2, 2, 1}}), equalTo(1.0)); } @Test diff --git a/src/test/java/g3401_3500/s3456_find_special_substring_of_length_k/SolutionTest.java b/src/test/java/g3401_3500/s3456_find_special_substring_of_length_k/SolutionTest.java index 5c40b70b3..e94179988 100644 --- a/src/test/java/g3401_3500/s3456_find_special_substring_of_length_k/SolutionTest.java +++ b/src/test/java/g3401_3500/s3456_find_special_substring_of_length_k/SolutionTest.java @@ -15,4 +15,9 @@ void hasSpecialSubstring() { void hasSpecialSubstring2() { assertThat(new Solution().hasSpecialSubstring("abc", 2), equalTo(false)); } + + @Test + void hasSpecialSubstring3() { + assertThat(new Solution().hasSpecialSubstring("ccc", 2), equalTo(false)); + } } From 7fe7f8d33d27d6c36cf437f62aa23a0a4061c3a6 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Tue, 18 Feb 2025 08:23:52 +0200 Subject: [PATCH 11/11] Fixed sonar --- .../java/g3401_3500/s3453_separate_squares_i/Solution.java | 4 ++-- .../java/g3401_3500/s3454_separate_squares_ii/Solution.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java b/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java index fef0c84fb..cd0f4c101 100644 --- a/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java +++ b/src/main/java/g3401_3500/s3453_separate_squares_i/Solution.java @@ -8,7 +8,7 @@ public double separateSquares(int[][] squares) { long lo = 1_000_000_000L; for (int[] q : squares) { lo = Math.min(lo, q[1]); - hi = Math.max(hi, q[1] + q[2]); + hi = Math.max(hi, q[1] + (long) q[2]); } while (lo <= hi) { long mid = (lo + hi) / 2; @@ -20,7 +20,7 @@ public double separateSquares(int[][] squares) { } double diff1 = diff(hi, squares); double diff2 = diff(lo, squares); - return (double) hi + diff1 / (diff1 - diff2); + return hi + diff1 / (diff1 - diff2); } private double diff(long mid, int[][] squares) { diff --git a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java index 557d2f463..c8533f2b7 100644 --- a/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java +++ b/src/main/java/g3401_3500/s3454_separate_squares_ii/Solution.java @@ -7,6 +7,7 @@ import java.util.Arrays; import java.util.List; +@SuppressWarnings("java:S1210") public class Solution { private static class Event implements Comparable { double y; @@ -65,7 +66,7 @@ void update(int idx, int l, int r, int ql, int qr, int val) { update(2 * idx + 2, mid + 1, r, ql, qr, val); } if (count[idx] > 0) { - len[idx] = x[r + 1] - x[l]; + len[idx] = x[r + 1] - (double) x[l]; } else { if (l == r) { len[idx] = 0;