diff --git a/src/main/java/g3401_3500/s3483_unique_3_digit_even_numbers/Solution.java b/src/main/java/g3401_3500/s3483_unique_3_digit_even_numbers/Solution.java new file mode 100644 index 000000000..e69cc69b1 --- /dev/null +++ b/src/main/java/g3401_3500/s3483_unique_3_digit_even_numbers/Solution.java @@ -0,0 +1,33 @@ +package g3401_3500.s3483_unique_3_digit_even_numbers; + +// #Easy #Array #Hash_Table #Recursion #Enumeration +// #2025_03_17_Time_5_ms_(100.00%)_Space_44.59_MB_(100.00%) + +import java.util.HashSet; + +public class Solution { + public int totalNumbers(int[] digits) { + HashSet set = new HashSet<>(); + int n = digits.length; + for (int i = 0; i < n; i++) { + if (digits[i] == 0) { + continue; + } + for (int j = 0; j < n; j++) { + if (j == i) { + continue; + } + for (int k = 0; k < n; k++) { + if (k == i || k == j) { + continue; + } + if (digits[k] % 2 == 0) { + int number = digits[i] * 100 + digits[j] * 10 + digits[k]; + set.add(number); + } + } + } + } + return set.size(); + } +} diff --git a/src/main/java/g3401_3500/s3483_unique_3_digit_even_numbers/readme.md b/src/main/java/g3401_3500/s3483_unique_3_digit_even_numbers/readme.md new file mode 100644 index 000000000..1d224025e --- /dev/null +++ b/src/main/java/g3401_3500/s3483_unique_3_digit_even_numbers/readme.md @@ -0,0 +1,44 @@ +3483\. Unique 3-Digit Even Numbers + +Easy + +You are given an array of digits called `digits`. Your task is to determine the number of **distinct** three-digit even numbers that can be formed using these digits. + +**Note**: Each _copy_ of a digit can only be used **once per number**, and there may **not** be leading zeros. + +**Example 1:** + +**Input:** digits = [1,2,3,4] + +**Output:** 12 + +**Explanation:** The 12 distinct 3-digit even numbers that can be formed are 124, 132, 134, 142, 214, 234, 312, 314, 324, 342, 412, and 432. Note that 222 cannot be formed because there is only 1 copy of the digit 2. + +**Example 2:** + +**Input:** digits = [0,2,2] + +**Output:** 2 + +**Explanation:** The only 3-digit even numbers that can be formed are 202 and 220. Note that the digit 2 can be used twice because it appears twice in the array. + +**Example 3:** + +**Input:** digits = [6,6,6] + +**Output:** 1 + +**Explanation:** Only 666 can be formed. + +**Example 4:** + +**Input:** digits = [1,3,5] + +**Output:** 0 + +**Explanation:** No even 3-digit numbers can be formed. + +**Constraints:** + +* `3 <= digits.length <= 10` +* `0 <= digits[i] <= 9` \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3484_design_spreadsheet/Spreadsheet.java b/src/main/java/g3401_3500/s3484_design_spreadsheet/Spreadsheet.java new file mode 100644 index 000000000..347c67023 --- /dev/null +++ b/src/main/java/g3401_3500/s3484_design_spreadsheet/Spreadsheet.java @@ -0,0 +1,45 @@ +package g3401_3500.s3484_design_spreadsheet; + +// #Medium #Array #String #Hash_Table #Matrix #Design +// #2025_03_17_Time_117_ms_(100.00%)_Space_56.71_MB_(100.00%) + +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("unused") +public class Spreadsheet { + private final Map data = new HashMap<>(); + + public Spreadsheet(int rows) {} + + public void setCell(String cell, int value) { + data.put(cell, value); + } + + public void resetCell(String cell) { + data.put(cell, 0); + } + + public int getValue(String formula) { + int index = formula.indexOf('+'); + String left = formula.substring(1, index); + String right = formula.substring(index + 1); + int x = + Character.isLetter(left.charAt(0)) + ? data.getOrDefault(left, 0) + : Integer.parseInt(left); + int y = + Character.isLetter(right.charAt(0)) + ? data.getOrDefault(right, 0) + : Integer.parseInt(right); + return x + y; + } +} + +/* + * Your Spreadsheet object will be instantiated and called as such: + * Spreadsheet obj = new Spreadsheet(rows); + * obj.setCell(cell,value); + * obj.resetCell(cell); + * int param_3 = obj.getValue(formula); + */ diff --git a/src/main/java/g3401_3500/s3484_design_spreadsheet/readme.md b/src/main/java/g3401_3500/s3484_design_spreadsheet/readme.md new file mode 100644 index 000000000..dfbec7a7d --- /dev/null +++ b/src/main/java/g3401_3500/s3484_design_spreadsheet/readme.md @@ -0,0 +1,44 @@ +3484\. Design Spreadsheet + +Medium + +A spreadsheet is a grid with 26 columns (labeled from `'A'` to `'Z'`) and a given number of `rows`. Each cell in the spreadsheet can hold an integer value between 0 and 105. + +Implement the `Spreadsheet` class: + +* `Spreadsheet(int rows)` Initializes a spreadsheet with 26 columns (labeled `'A'` to `'Z'`) and the specified number of rows. All cells are initially set to 0. +* `void setCell(String cell, int value)` Sets the value of the specified `cell`. The cell reference is provided in the format `"AX"` (e.g., `"A1"`, `"B10"`), where the letter represents the column (from `'A'` to `'Z'`) and the number represents a **1-indexed** row. +* `void resetCell(String cell)` Resets the specified cell to 0. +* `int getValue(String formula)` Evaluates a formula of the form `"=X+Y"`, where `X` and `Y` are **either** cell references or non-negative integers, and returns the computed sum. + +**Note:** If `getValue` references a cell that has not been explicitly set using `setCell`, its value is considered 0. + +**Example 1:** + +**Input:** + ["Spreadsheet", "getValue", "setCell", "getValue", "setCell", "getValue", "resetCell", "getValue"] + [[3], ["=5+7"], ["A1", 10], ["=A1+6"], ["B2", 15], ["=A1+B2"], ["A1"], ["=A1+B2"]] + +**Output:** + [null, 12, null, 16, null, 25, null, 15] + +**Explanation** + +```java +Spreadsheet spreadsheet = new Spreadsheet(3); // Initializes a spreadsheet with 3 rows and 26 columns +spreadsheet.getValue("=5+7"); // returns 12 (5+7) +spreadsheet.setCell("A1", 10); // sets A1 to 10 +spreadsheet.getValue("=A1+6"); // returns 16 (10+6) +spreadsheet.setCell("B2", 15); // sets B2 to 15 +spreadsheet.getValue("=A1+B2"); // returns 25 (10+15) +spreadsheet.resetCell("A1"); // resets A1 to 0 +spreadsheet.getValue("=A1+B2"); // returns 15 (0+15) +``` + +**Constraints:** + +* 1 <= rows <= 103 +* 0 <= value <= 105 +* The formula is always in the format `"=X+Y"`, where `X` and `Y` are either valid cell references or **non-negative** integers with values less than or equal to 105. +* Each cell reference consists of a capital letter from `'A'` to `'Z'` followed by a row number between `1` and `rows`. +* At most 104 calls will be made in **total** to `setCell`, `resetCell`, and `getValue`. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/Solution.java b/src/main/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/Solution.java new file mode 100644 index 000000000..ffe2cb6c2 --- /dev/null +++ b/src/main/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/Solution.java @@ -0,0 +1,67 @@ +package g3401_3500.s3485_longest_common_prefix_of_k_strings_after_removal; + +// #Hard #Array #String #Trie #2025_03_17_Time_333_ms_(100.00%)_Space_64.12_MB_(100.00%) + +public class Solution { + private static class TrieNode { + TrieNode[] children = new TrieNode[26]; + int count = 0; + int bestPrefixLength = -1; + } + + private TrieNode root; + + public int[] longestCommonPrefix(String[] words, int k) { + int totalWords = words.length; + int[] result = new int[totalWords]; + if (totalWords - 1 < k) { + return result; + } + root = new TrieNode(); + for (String word : words) { + // insert the word with increasing the count by 1 (prefix count) + updateTrie(word, 1, k); + } + for (int i = 0; i < totalWords; i++) { + // temp deletion of the word with count decreased by 1 + updateTrie(words[i], -1, k); + result[i] = root.bestPrefixLength; + // re-insertion of the word + updateTrie(words[i], 1, k); + } + return result; + } + + private void updateTrie(String word, int count, int k) { + int wordLength = word.length(); + // used to store the path used during trie travesal to update the count and use the count + TrieNode[] nodePath = new TrieNode[wordLength + 1]; + int[] depths = new int[wordLength + 1]; + nodePath[0] = root; + depths[0] = 0; + // trie insertion + for (int i = 0; i < wordLength; i++) { + int letterIndex = word.charAt(i) - 'a'; + if (nodePath[i].children[letterIndex] == null) { + nodePath[i].children[letterIndex] = new TrieNode(); + } + nodePath[i + 1] = nodePath[i].children[letterIndex]; + depths[i + 1] = depths[i] + 1; + } + // increase the count of each prefix + for (TrieNode node : nodePath) { + node.count += count; + } + // find the best prefix + for (int i = nodePath.length - 1; i >= 0; i--) { + TrieNode currentNode = nodePath[i]; + int candidate = (currentNode.count >= k ? depths[i] : -1); + for (TrieNode childNode : currentNode.children) { + if (childNode != null) { + candidate = Math.max(candidate, childNode.bestPrefixLength); + } + } + currentNode.bestPrefixLength = candidate; + } + } +} diff --git a/src/main/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/readme.md b/src/main/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/readme.md new file mode 100644 index 000000000..d5f900575 --- /dev/null +++ b/src/main/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/readme.md @@ -0,0 +1,45 @@ +3485\. Longest Common Prefix of K Strings After Removal + +Hard + +You are given an array of strings `words` and an integer `k`. + +For each index `i` in the range `[0, words.length - 1]`, find the **length** of the **longest common prefix** among any `k` strings (selected at **distinct indices**) from the remaining array after removing the ith element. + +Return an array `answer`, where `answer[i]` is the answer for ith element. If removing the ith element leaves the array with fewer than `k` strings, `answer[i]` is 0. + +**Example 1:** + +**Input:** words = ["jump","run","run","jump","run"], k = 2 + +**Output:** [3,4,4,3,4] + +**Explanation:** + +* Removing index 0 (`"jump"`): + * `words` becomes: `["run", "run", "jump", "run"]`. `"run"` occurs 3 times. Choosing any two gives the longest common prefix `"run"` (length 3). +* Removing index 1 (`"run"`): + * `words` becomes: `["jump", "run", "jump", "run"]`. `"jump"` occurs twice. Choosing these two gives the longest common prefix `"jump"` (length 4). +* Removing index 2 (`"run"`): + * `words` becomes: `["jump", "run", "jump", "run"]`. `"jump"` occurs twice. Choosing these two gives the longest common prefix `"jump"` (length 4). +* Removing index 3 (`"jump"`): + * `words` becomes: `["jump", "run", "run", "run"]`. `"run"` occurs 3 times. Choosing any two gives the longest common prefix `"run"` (length 3). +* Removing index 4 ("run"): + * `words` becomes: `["jump", "run", "run", "jump"]`. `"jump"` occurs twice. Choosing these two gives the longest common prefix `"jump"` (length 4). + +**Example 2:** + +**Input:** words = ["dog","racer","car"], k = 2 + +**Output:** [0,0,0] + +**Explanation:** + +* Removing any index results in an answer of 0. + +**Constraints:** + +* 1 <= k <= words.length <= 105 +* 1 <= words[i].length <= 104 +* `words[i]` consists of lowercase English letters. +* The sum of `words[i].length` is smaller than or equal 105. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3486_longest_special_path_ii/Solution.java b/src/main/java/g3401_3500/s3486_longest_special_path_ii/Solution.java new file mode 100644 index 000000000..f54901302 --- /dev/null +++ b/src/main/java/g3401_3500/s3486_longest_special_path_ii/Solution.java @@ -0,0 +1,69 @@ +package g3401_3500.s3486_longest_special_path_ii; + +// #Hard #Array #Hash_Table #Tree #Prefix_Sum #Depth_First_Search +// #2025_03_17_Time_166_ms_(100.00%)_Space_105.50_MB_(100.00%) + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("java:S107") +public class Solution { + public int[] longestSpecialPath(int[][] edges, int[] nums) { + int[] ans = {0, 1}; + Map> graph = new HashMap<>(); + for (int[] edge : edges) { + int a = edge[0]; + int b = edge[1]; + int c = edge[2]; + graph.computeIfAbsent(a, k -> new ArrayList<>()).add(new int[] {b, c}); + graph.computeIfAbsent(b, k -> new ArrayList<>()).add(new int[] {a, c}); + } + List costs = new ArrayList<>(); + Map last = new HashMap<>(); + dfs(0, 0, -1, new ArrayList<>(Arrays.asList(0, 0)), nums, graph, costs, last, ans); + return ans; + } + + private void dfs( + int node, + int currCost, + int prev, + List left, + int[] nums, + Map> graph, + List costs, + Map last, + int[] ans) { + int nodeColorIndexPrev = last.getOrDefault(nums[node], -1); + last.put(nums[node], costs.size()); + costs.add(currCost); + int diff = currCost - costs.get(left.get(0)); + int length = costs.size() - left.get(0); + if (diff > ans[0] || (diff == ans[0] && length < ans[1])) { + ans[0] = diff; + ans[1] = length; + } + for (int[] next : graph.getOrDefault(node, new ArrayList<>())) { + int nextNode = next[0]; + int nextCost = next[1]; + if (nextNode == prev) { + continue; + } + List nextLeft = new ArrayList<>(left); + if (last.containsKey(nums[nextNode])) { + nextLeft.add(last.get(nums[nextNode]) + 1); + } + nextLeft.sort(Comparator.naturalOrder()); + while (nextLeft.size() > 2) { + nextLeft.remove(0); + } + dfs(nextNode, currCost + nextCost, node, nextLeft, nums, graph, costs, last, ans); + } + last.put(nums[node], nodeColorIndexPrev); + costs.remove(costs.size() - 1); + } +} diff --git a/src/main/java/g3401_3500/s3486_longest_special_path_ii/readme.md b/src/main/java/g3401_3500/s3486_longest_special_path_ii/readme.md new file mode 100644 index 000000000..b623d0577 --- /dev/null +++ b/src/main/java/g3401_3500/s3486_longest_special_path_ii/readme.md @@ -0,0 +1,46 @@ +3486\. Longest Special Path II + +Hard + +You are given an undirected tree rooted at node `0`, with `n` nodes numbered from `0` to `n - 1`. This is represented by a 2D array `edges` of length `n - 1`, where edges[i] = [ui, vi, lengthi] indicates an edge between nodes ui and vi with length lengthi. You are also given an integer array `nums`, where `nums[i]` represents the value at node `i`. + +A **special path** is defined as a **downward** path from an ancestor node to a descendant node in which all node values are **distinct**, except for **at most** one value that may appear twice. + +Return an array `result` of size 2, where `result[0]` is the **length** of the **longest** special path, and `result[1]` is the **minimum** number of nodes in all _possible_ **longest** special paths. + +**Example 1:** + +**Input:** edges = [[0,1,1],[1,2,3],[1,3,1],[2,4,6],[4,7,2],[3,5,2],[3,6,5],[6,8,3]], nums = [1,1,0,3,1,2,1,1,0] + +**Output:** [9,3] + +**Explanation:** + +In the image below, nodes are colored by their corresponding values in `nums`. + +![](https://assets.leetcode.com/uploads/2025/02/18/e1.png) + +The longest special paths are `1 -> 2 -> 4` and `1 -> 3 -> 6 -> 8`, both having a length of 9. The minimum number of nodes across all longest special paths is 3. + +**Example 2:** + +**Input:** edges = [[1,0,3],[0,2,4],[0,3,5]], nums = [1,1,0,2] + +**Output:** [5,2] + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/02/18/e2.png) + +The longest path is `0 -> 3` consisting of 2 nodes with a length of 5. + +**Constraints:** + +* 2 <= n <= 5 * 104 +* `edges.length == n - 1` +* `edges[i].length == 3` +* 0 <= ui, vi < n +* 1 <= lengthi <= 103 +* `nums.length == n` +* 0 <= nums[i] <= 5 * 104 +* The input is generated such that `edges` represents a valid tree. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/Solution.java b/src/main/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/Solution.java new file mode 100644 index 000000000..6cfa84001 --- /dev/null +++ b/src/main/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/Solution.java @@ -0,0 +1,29 @@ +package g3401_3500.s3487_maximum_unique_subarray_sum_after_deletion; + +// #Easy #Array #Hash_Table #Greedy #2025_03_17_Time_2_ms_(100.00%)_Space_42.64_MB_(100.00%) + +import java.util.HashSet; +import java.util.Set; + +public class Solution { + public int maxSum(int[] nums) { + int sum = 0; + Set st = new HashSet<>(); + int mxNeg = Integer.MIN_VALUE; + for (int num : nums) { + if (num > 0) { + st.add(num); + } else { + mxNeg = Math.max(mxNeg, num); + } + } + for (int val : st) { + sum += val; + } + if (!st.isEmpty()) { + return sum; + } else { + return mxNeg; + } + } +} diff --git a/src/main/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/readme.md b/src/main/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/readme.md new file mode 100644 index 000000000..8568b7a23 --- /dev/null +++ b/src/main/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/readme.md @@ -0,0 +1,47 @@ +3487\. Maximum Unique Subarray Sum After Deletion + +Easy + +You are given an integer array `nums`. + +You are allowed to delete any number of elements from `nums` without making it **empty**. After performing the deletions, select a non-empty subarrays of `nums` such that: + +1. All elements in the subarray are **unique**. +2. The sum of the elements in the subarray is **maximized**. + +Return the **maximum sum** of such a subarray. + +**Example 1:** + +**Input:** nums = [1,2,3,4,5] + +**Output:** 15 + +**Explanation:** + +Select the entire array without deleting any element to obtain the maximum sum. + +**Example 2:** + +**Input:** nums = [1,1,0,1,1] + +**Output:** 1 + +**Explanation:** + +Delete the element `nums[0] == 1`, `nums[1] == 1`, `nums[2] == 0`, and `nums[3] == 1`. Select the entire array `[1]` to obtain the maximum sum. + +**Example 3:** + +**Input:** nums = [1,2,-1,-2,1,0,-1] + +**Output:** 3 + +**Explanation:** + +Delete the elements `nums[2] == -1` and `nums[3] == -2`, and select the subarray `[2, 1]` from `[1, 2, 1, 0, -1]` to obtain the maximum sum. + +**Constraints:** + +* `1 <= nums.length <= 100` +* `-100 <= nums[i] <= 100` \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3488_closest_equal_element_queries/Solution.java b/src/main/java/g3401_3500/s3488_closest_equal_element_queries/Solution.java new file mode 100644 index 000000000..53b9ad5c6 --- /dev/null +++ b/src/main/java/g3401_3500/s3488_closest_equal_element_queries/Solution.java @@ -0,0 +1,39 @@ +package g3401_3500.s3488_closest_equal_element_queries; + +// #Medium #Array #Hash_Table #Binary_Search +// #2025_03_17_Time_50_ms_(100.00%)_Space_74.96_MB_(100.00%) + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Solution { + public List solveQueries(int[] nums, int[] queries) { + int sz = nums.length; + Map> indices = new HashMap<>(); + for (int i = 0; i < sz; i++) { + indices.computeIfAbsent(nums[i], k -> new ArrayList<>()).add(i); + } + for (List arr : indices.values()) { + int m = arr.size(); + if (m == 1) { + nums[arr.get(0)] = -1; + continue; + } + for (int i = 0; i < m; i++) { + int j = arr.get(i); + int f = arr.get((i + 1) % m); + int b = arr.get((i - 1 + m) % m); + int forward = Math.min((sz - j - 1) + f + 1, Math.abs(j - f)); + int backward = Math.min(Math.abs(b - j), j + (sz - b)); + nums[j] = Math.min(backward, forward); + } + } + List res = new ArrayList<>(); + for (int q : queries) { + res.add(nums[q]); + } + return res; + } +} diff --git a/src/main/java/g3401_3500/s3488_closest_equal_element_queries/readme.md b/src/main/java/g3401_3500/s3488_closest_equal_element_queries/readme.md new file mode 100644 index 000000000..aa812bd8f --- /dev/null +++ b/src/main/java/g3401_3500/s3488_closest_equal_element_queries/readme.md @@ -0,0 +1,39 @@ +3488\. Closest Equal Element Queries + +Medium + +You are given a **circular** array `nums` and an array `queries`. + +For each query `i`, you have to find the following: + +* The **minimum** distance between the element at index `queries[i]` and **any** other index `j` in the **circular** array, where `nums[j] == nums[queries[i]]`. If no such index exists, the answer for that query should be -1. + +Return an array `answer` of the **same** size as `queries`, where `answer[i]` represents the result for query `i`. + +**Example 1:** + +**Input:** nums = [1,3,1,4,1,3,2], queries = [0,3,5] + +**Output:** [2,-1,3] + +**Explanation:** + +* Query 0: The element at `queries[0] = 0` is `nums[0] = 1`. The nearest index with the same value is 2, and the distance between them is 2. +* Query 1: The element at `queries[1] = 3` is `nums[3] = 4`. No other index contains 4, so the result is -1. +* Query 2: The element at `queries[2] = 5` is `nums[5] = 3`. The nearest index with the same value is 1, and the distance between them is 3 (following the circular path: `5 -> 6 -> 0 -> 1`). + +**Example 2:** + +**Input:** nums = [1,2,3,4], queries = [0,1,2,3] + +**Output:** [-1,-1,-1,-1] + +**Explanation:** + +Each value in `nums` is unique, so no index shares the same value as the queried element. This results in -1 for all queries. + +**Constraints:** + +* 1 <= queries.length <= nums.length <= 105 +* 1 <= nums[i] <= 106 +* `0 <= queries[i] < nums.length` \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3489_zero_array_transformation_iv/Solution.java b/src/main/java/g3401_3500/s3489_zero_array_transformation_iv/Solution.java new file mode 100644 index 000000000..fc301ab44 --- /dev/null +++ b/src/main/java/g3401_3500/s3489_zero_array_transformation_iv/Solution.java @@ -0,0 +1,39 @@ +package g3401_3500.s3489_zero_array_transformation_iv; + +// #Medium #Array #Dynamic_Programming #2025_03_17_Time_142_ms_(100.00%)_Space_56.22_MB_(100.00%) + +import java.util.Arrays; + +public class Solution { + private int solve(int[][] q, int i, int target, int k, int[][] dp) { + // we found a valid sum equal to target so return current index of query. + if (target == 0) { + return k; + } + // return a larger number to invalidate this flow + if (k >= q.length || target < 0) { + return q.length + 1; + } + if (dp[target][k] != -1) { + return dp[target][k]; + } + // skip current query val + int res = solve(q, i, target, k + 1, dp); + // pick the val if its range is in the range of target index + if (q[k][0] <= i && i <= q[k][1]) { + res = Math.min(res, solve(q, i, target - q[k][2], k + 1, dp)); + } + dp[target][k] = res; + return res; + } + + public int minZeroArray(int[] nums, int[][] queries) { + int ans = -1; + for (int i = 0; i < nums.length; ++i) { + int[][] dp = new int[nums[i] + 1][queries.length]; + Arrays.stream(dp).forEach(row -> Arrays.fill(row, -1)); + ans = Math.max(ans, solve(queries, i, nums[i], 0, dp)); + } + return (ans > queries.length) ? -1 : ans; + } +} diff --git a/src/main/java/g3401_3500/s3489_zero_array_transformation_iv/readme.md b/src/main/java/g3401_3500/s3489_zero_array_transformation_iv/readme.md new file mode 100644 index 000000000..a516f13c8 --- /dev/null +++ b/src/main/java/g3401_3500/s3489_zero_array_transformation_iv/readme.md @@ -0,0 +1,75 @@ +3489\. Zero Array Transformation IV + +Medium + +You are given an integer array `nums` of length `n` and a 2D array `queries`, where queries[i] = [li, ri, vali]. + +Each `queries[i]` represents the following action on `nums`: + +* Select a **subset** of indices in the range [li, ri] from `nums`. +* Decrement the value at each selected index by **exactly** vali. + +A **Zero Array** is an array with all its elements equal to 0. + +Return the **minimum** possible **non-negative** value of `k`, such that after processing the first `k` queries in **sequence**, `nums` becomes a **Zero Array**. If no such `k` exists, return -1. + +**Example 1:** + +**Input:** nums = [2,0,2], queries = [[0,2,1],[0,2,1],[1,1,3]] + +**Output:** 2 + +**Explanation:** + +* **For query 0 (l = 0, r = 2, val = 1):** + * Decrement the values at indices `[0, 2]` by 1. + * The array will become `[1, 0, 1]`. +* **For query 1 (l = 0, r = 2, val = 1):** + * Decrement the values at indices `[0, 2]` by 1. + * The array will become `[0, 0, 0]`, which is a Zero Array. Therefore, the minimum value of `k` is 2. + +**Example 2:** + +**Input:** nums = [4,3,2,1], queries = [[1,3,2],[0,2,1]] + +**Output:** \-1 + +**Explanation:** + +It is impossible to make nums a Zero Array even after all the queries. + +**Example 3:** + +**Input:** nums = [1,2,3,2,1], queries = [[0,1,1],[1,2,1],[2,3,2],[3,4,1],[4,4,1]] + +**Output:** 4 + +**Explanation:** + +* **For query 0 (l = 0, r = 1, val = 1):** + * Decrement the values at indices `[0, 1]` by `1`. + * The array will become `[0, 1, 3, 2, 1]`. +* **For query 1 (l = 1, r = 2, val = 1):** + * Decrement the values at indices `[1, 2]` by 1. + * The array will become `[0, 0, 2, 2, 1]`. +* **For query 2 (l = 2, r = 3, val = 2):** + * Decrement the values at indices `[2, 3]` by 2. + * The array will become `[0, 0, 0, 0, 1]`. +* **For query 3 (l = 3, r = 4, val = 1):** + * Decrement the value at index 4 by 1. + * The array will become `[0, 0, 0, 0, 0]`. Therefore, the minimum value of `k` is 4. + +**Example 4:** + +**Input:** nums = [1,2,3,2,6], queries = [[0,1,1],[0,2,1],[1,4,2],[4,4,4],[3,4,1],[4,4,5]] + +**Output:** 4 + +**Constraints:** + +* `1 <= nums.length <= 10` +* `0 <= nums[i] <= 1000` +* `1 <= queries.length <= 1000` +* queries[i] = [li, ri, vali] +* 0 <= li <= ri < nums.length +* 1 <= vali <= 10 \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3490_count_beautiful_numbers/Solution.java b/src/main/java/g3401_3500/s3490_count_beautiful_numbers/Solution.java new file mode 100644 index 000000000..2dfffbc49 --- /dev/null +++ b/src/main/java/g3401_3500/s3490_count_beautiful_numbers/Solution.java @@ -0,0 +1,62 @@ +package g3401_3500.s3490_count_beautiful_numbers; + +// #Hard #Dynamic_Programming #2025_03_17_Time_523_ms_(100.00%)_Space_55.41_MB_(100.00%) + +import java.util.HashMap; + +public class Solution { + public int beautifulNumbers(int l, int r) { + return countBeautiful(r) - countBeautiful(l - 1); + } + + private int countBeautiful(int x) { + char[] digits = getCharArray(x); + HashMap dp = new HashMap<>(); + return solve(0, 1, 0, 1, digits, dp); + } + + private char[] getCharArray(int x) { + String str = String.valueOf(x); + return str.toCharArray(); + } + + private int solve( + int i, int tight, int sum, int prod, char[] digits, HashMap dp) { + if (i == digits.length) { + if (sum > 0 && prod % sum == 0) { + return 1; + } else { + return 0; + } + } + String str = i + " - " + tight + " - " + sum + " - " + prod; + if (dp.containsKey(str)) { + return dp.get(str); + } + int limit; + if (tight == 1) { + limit = digits[i] - '0'; + } else { + limit = 9; + } + int count = 0; + int j = 0; + while (j <= limit) { + int newTight = 0; + if (tight == 1 && j == limit) { + newTight = 1; + } + int newSum = sum + j; + int newProd; + if (j == 0 && sum == 0) { + newProd = 1; + } else { + newProd = prod * j; + } + count += solve(i + 1, newTight, newSum, newProd, digits, dp); + j++; + } + dp.put(str, count); + return count; + } +} diff --git a/src/main/java/g3401_3500/s3490_count_beautiful_numbers/readme.md b/src/main/java/g3401_3500/s3490_count_beautiful_numbers/readme.md new file mode 100644 index 000000000..123c58616 --- /dev/null +++ b/src/main/java/g3401_3500/s3490_count_beautiful_numbers/readme.md @@ -0,0 +1,31 @@ +3490\. Count Beautiful Numbers + +Hard + +You are given two positive integers, `l` and `r`. A positive integer is called **beautiful** if the product of its digits is divisible by the sum of its digits. + +Return the count of **beautiful** numbers between `l` and `r`, inclusive. + +**Example 1:** + +**Input:** l = 10, r = 20 + +**Output:** 2 + +**Explanation:** + +The beautiful numbers in the range are 10 and 20. + +**Example 2:** + +**Input:** l = 1, r = 15 + +**Output:** 10 + +**Explanation:** + +The beautiful numbers in the range are 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10. + +**Constraints:** + +* 1 <= l <= r < 109 \ No newline at end of file diff --git a/src/test/java/g3401_3500/s3483_unique_3_digit_even_numbers/SolutionTest.java b/src/test/java/g3401_3500/s3483_unique_3_digit_even_numbers/SolutionTest.java new file mode 100644 index 000000000..98dfd0642 --- /dev/null +++ b/src/test/java/g3401_3500/s3483_unique_3_digit_even_numbers/SolutionTest.java @@ -0,0 +1,28 @@ +package g3401_3500.s3483_unique_3_digit_even_numbers; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void totalNumbers() { + assertThat(new Solution().totalNumbers(new int[] {1, 2, 3, 4}), equalTo(12)); + } + + @Test + void totalNumbers2() { + assertThat(new Solution().totalNumbers(new int[] {0, 2, 2}), equalTo(2)); + } + + @Test + void totalNumbers3() { + assertThat(new Solution().totalNumbers(new int[] {6, 6, 6}), equalTo(1)); + } + + @Test + void totalNumbers4() { + assertThat(new Solution().totalNumbers(new int[] {1, 3, 5}), equalTo(0)); + } +} diff --git a/src/test/java/g3401_3500/s3484_design_spreadsheet/SpreadsheetTest.java b/src/test/java/g3401_3500/s3484_design_spreadsheet/SpreadsheetTest.java new file mode 100644 index 000000000..d789ac32a --- /dev/null +++ b/src/test/java/g3401_3500/s3484_design_spreadsheet/SpreadsheetTest.java @@ -0,0 +1,28 @@ +package g3401_3500.s3484_design_spreadsheet; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SpreadsheetTest { + @Test + void spreadsheet() { + // Initializes a spreadsheet with 3 rows and 26 columns + Spreadsheet spreadsheet = new Spreadsheet(3); + // returns 12 (5+7) + assertThat(spreadsheet.getValue("=5+7"), equalTo(12)); + // sets A1 to 10 + spreadsheet.setCell("A1", 10); + // returns 16 (10+6) + assertThat(spreadsheet.getValue("=A1+6"), equalTo(16)); + // sets B2 to 15 + spreadsheet.setCell("B2", 15); + // returns 25 (10+15) + assertThat(spreadsheet.getValue("=A1+B2"), equalTo(25)); + // resets A1 to 0 + spreadsheet.resetCell("A1"); + // returns 15 (0+15) + assertThat(spreadsheet.getValue("=A1+B2"), equalTo(15)); + } +} diff --git a/src/test/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/SolutionTest.java b/src/test/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/SolutionTest.java new file mode 100644 index 000000000..77c97a241 --- /dev/null +++ b/src/test/java/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/SolutionTest.java @@ -0,0 +1,30 @@ +package g3401_3500.s3485_longest_common_prefix_of_k_strings_after_removal; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void longestCommonPrefix() { + assertThat( + new Solution() + .longestCommonPrefix(new String[] {"jump", "run", "run", "jump", "run"}, 2), + equalTo(new int[] {3, 4, 4, 3, 4})); + } + + @Test + void longestCommonPrefix2() { + assertThat( + new Solution().longestCommonPrefix(new String[] {"dog", "racer", "car"}, 2), + equalTo(new int[] {0, 0, 0})); + } + + @Test + void longestCommonPrefix3() { + assertThat( + new Solution().longestCommonPrefix(new String[] {"cdbff"}, 1), + equalTo(new int[] {0})); + } +} diff --git a/src/test/java/g3401_3500/s3486_longest_special_path_ii/SolutionTest.java b/src/test/java/g3401_3500/s3486_longest_special_path_ii/SolutionTest.java new file mode 100644 index 000000000..0f5e424bb --- /dev/null +++ b/src/test/java/g3401_3500/s3486_longest_special_path_ii/SolutionTest.java @@ -0,0 +1,41 @@ +package g3401_3500.s3486_longest_special_path_ii; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void longestSpecialPath() { + assertThat( + new Solution() + .longestSpecialPath( + new int[][] { + {0, 1, 1}, {1, 2, 3}, {1, 3, 1}, {2, 4, 6}, {4, 7, 2}, + {3, 5, 2}, {3, 6, 5}, {6, 8, 3} + }, + new int[] {1, 1, 0, 3, 1, 2, 1, 1, 0}), + equalTo(new int[] {9, 3})); + } + + @Test + void longestSpecialPath2() { + assertThat( + new Solution() + .longestSpecialPath( + new int[][] {{1, 0, 3}, {0, 2, 4}, {0, 3, 5}}, + new int[] {1, 1, 0, 2}), + equalTo(new int[] {5, 2})); + } + + @Test + void longestSpecialPath3() { + assertThat( + new Solution() + .longestSpecialPath( + new int[][] {{0, 2, 4}, {1, 2, 10}, {3, 1, 5}}, + new int[] {4, 5, 4, 5}), + equalTo(new int[] {15, 3})); + } +} diff --git a/src/test/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/SolutionTest.java b/src/test/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/SolutionTest.java new file mode 100644 index 000000000..c591a8a8c --- /dev/null +++ b/src/test/java/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/SolutionTest.java @@ -0,0 +1,28 @@ +package g3401_3500.s3487_maximum_unique_subarray_sum_after_deletion; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void maxSum() { + assertThat(new Solution().maxSum(new int[] {1, 2, 3, 4, 5}), equalTo(15)); + } + + @Test + void maxSum2() { + assertThat(new Solution().maxSum(new int[] {1, 1, 0, 1, 1}), equalTo(1)); + } + + @Test + void maxSum3() { + assertThat(new Solution().maxSum(new int[] {1, 2, -1, -2, 1, 0, -1}), equalTo(3)); + } + + @Test + void maxSum4() { + assertThat(new Solution().maxSum(new int[] {-100}), equalTo(-100)); + } +} diff --git a/src/test/java/g3401_3500/s3488_closest_equal_element_queries/SolutionTest.java b/src/test/java/g3401_3500/s3488_closest_equal_element_queries/SolutionTest.java new file mode 100644 index 000000000..a69c662b9 --- /dev/null +++ b/src/test/java/g3401_3500/s3488_closest_equal_element_queries/SolutionTest.java @@ -0,0 +1,23 @@ +package g3401_3500.s3488_closest_equal_element_queries; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.List; +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void solveQueries() { + assertThat( + new Solution().solveQueries(new int[] {1, 3, 1, 4, 1, 3, 2}, new int[] {0, 3, 5}), + equalTo(List.of(2, -1, 3))); + } + + @Test + void solveQueries2() { + assertThat( + new Solution().solveQueries(new int[] {1, 2, 3, 4}, new int[] {0, 1, 2, 3}), + equalTo(List.of(-1, -1, -1, -1))); + } +} diff --git a/src/test/java/g3401_3500/s3489_zero_array_transformation_iv/SolutionTest.java b/src/test/java/g3401_3500/s3489_zero_array_transformation_iv/SolutionTest.java new file mode 100644 index 000000000..466ed2ebb --- /dev/null +++ b/src/test/java/g3401_3500/s3489_zero_array_transformation_iv/SolutionTest.java @@ -0,0 +1,49 @@ +package g3401_3500.s3489_zero_array_transformation_iv; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minZeroArray() { + assertThat( + new Solution() + .minZeroArray( + new int[] {2, 0, 2}, new int[][] {{0, 2, 1}, {0, 2, 1}, {1, 1, 3}}), + equalTo(2)); + } + + @Test + void minZeroArray2() { + assertThat( + new Solution() + .minZeroArray(new int[] {4, 3, 2, 1}, new int[][] {{1, 3, 2}, {0, 2, 1}}), + equalTo(-1)); + } + + @Test + void minZeroArray3() { + assertThat( + new Solution() + .minZeroArray( + new int[] {1, 2, 3, 2, 1}, + new int[][] { + {0, 1, 1}, {1, 2, 1}, {2, 3, 2}, {3, 4, 1}, {4, 4, 1} + }), + equalTo(4)); + } + + @Test + void minZeroArray4() { + assertThat( + new Solution() + .minZeroArray( + new int[] {1, 2, 3, 2, 6}, + new int[][] { + {0, 1, 1}, {0, 2, 1}, {1, 4, 2}, {4, 4, 4}, {3, 4, 1}, {4, 4, 5} + }), + equalTo(4)); + } +} diff --git a/src/test/java/g3401_3500/s3490_count_beautiful_numbers/SolutionTest.java b/src/test/java/g3401_3500/s3490_count_beautiful_numbers/SolutionTest.java new file mode 100644 index 000000000..e7e31b504 --- /dev/null +++ b/src/test/java/g3401_3500/s3490_count_beautiful_numbers/SolutionTest.java @@ -0,0 +1,23 @@ +package g3401_3500.s3490_count_beautiful_numbers; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void beautifulNumbers() { + assertThat(new Solution().beautifulNumbers(10, 20), equalTo(2)); + } + + @Test + void beautifulNumbers2() { + assertThat(new Solution().beautifulNumbers(1, 15), equalTo(10)); + } + + @Test + void beautifulNumbers3() { + assertThat(new Solution().beautifulNumbers(6725, 270910825), equalTo(178996547)); + } +}