diff --git a/src/main/kotlin/g3401_3500/s3483_unique_3_digit_even_numbers/Solution.kt b/src/main/kotlin/g3401_3500/s3483_unique_3_digit_even_numbers/Solution.kt new file mode 100644 index 000000000..ab5873417 --- /dev/null +++ b/src/main/kotlin/g3401_3500/s3483_unique_3_digit_even_numbers/Solution.kt @@ -0,0 +1,31 @@ +package g3401_3500.s3483_unique_3_digit_even_numbers + +// #Easy #Array #Hash_Table #Recursion #Enumeration +// #2025_03_16_Time_6_ms_(100.00%)_Space_44.99_MB_(100.00%) + +class Solution { + fun totalNumbers(digits: IntArray): Int { + val set = HashSet() + val n = digits.size + for (i in 0.. = HashMap() + + fun setCell(cell: String, value: Int) { + data.put(cell, value) + } + + fun resetCell(cell: String) { + data.put(cell, 0) + } + + fun getValue(formula: String): Int { + val index = formula.indexOf('+') + val left = formula.substring(1, index) + val right = formula.substring(index + 1) + val x = + if (Character.isLetter(left[0])) { + data.getOrDefault(left, 0) + } else { + left.toInt() + } + val y = + if (Character.isLetter(right[0])) { + data.getOrDefault(right, 0) + } else { + right.toInt() + } + return x + y + } +} + +/* + * Your Spreadsheet object will be instantiated and called as such: + * var obj = Spreadsheet(rows) + * obj.setCell(cell,value) + * obj.resetCell(cell) + * var param_3 = obj.getValue(formula) + */ diff --git a/src/main/kotlin/g3401_3500/s3484_design_spreadsheet/readme.md b/src/main/kotlin/g3401_3500/s3484_design_spreadsheet/readme.md new file mode 100644 index 000000000..dfbec7a7d --- /dev/null +++ b/src/main/kotlin/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/kotlin/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/Solution.kt b/src/main/kotlin/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/Solution.kt new file mode 100644 index 000000000..1ebb88a18 --- /dev/null +++ b/src/main/kotlin/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/Solution.kt @@ -0,0 +1,69 @@ +package g3401_3500.s3485_longest_common_prefix_of_k_strings_after_removal + +// #Hard #Array #String #Trie #2025_03_16_Time_251_ms_(100.00%)_Space_86.10_MB_(100.00%) + +import kotlin.math.max + +class Solution { + private class TrieNode { + var children: Array = arrayOfNulls(26) + var count: Int = 0 + var bestPrefixLength: Int = -1 + } + + private var root: TrieNode? = null + + fun longestCommonPrefix(words: Array, k: Int): IntArray { + val totalWords = words.size + val result = IntArray(totalWords) + if (totalWords - 1 < k) { + return result + } + root = TrieNode() + for (word in words) { + // insert the word with increasing the count by 1 (prefix count) + updateTrie(word, 1, k) + } + for (i in 0.. = Array(wordLength + 1) { TrieNode() } + val depths = IntArray(wordLength + 1) + nodePath[0] = root!! + depths[0] = 0 + // trie insertion + for (i in 0..= k) depths[i] else -1) + for (childNode in currentNode.children) { + if (childNode != null) { + candidate = max(candidate, childNode.bestPrefixLength) + } + } + currentNode.bestPrefixLength = candidate + } + } +} diff --git a/src/main/kotlin/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/readme.md b/src/main/kotlin/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/kotlin/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/kotlin/g3401_3500/s3486_longest_special_path_ii/Solution.kt b/src/main/kotlin/g3401_3500/s3486_longest_special_path_ii/Solution.kt new file mode 100644 index 000000000..5b6f4142f --- /dev/null +++ b/src/main/kotlin/g3401_3500/s3486_longest_special_path_ii/Solution.kt @@ -0,0 +1,65 @@ +package g3401_3500.s3486_longest_special_path_ii + +// #Hard #Array #Hash_Table #Depth_First_Search #Tree #Prefix_Sum +// #2025_03_16_Time_255_ms_(100.00%)_Space_125.42_MB_(100.00%) + +@Suppress("kotlin:S107") +class Solution { + fun longestSpecialPath(edges: Array, nums: IntArray): IntArray { + val ans = intArrayOf(0, 1) + val graph: MutableMap> = HashMap>() + for (edge in edges) { + val a = edge[0] + val b = edge[1] + val c = edge[2] + graph.computeIfAbsent(a) { _: Int -> ArrayList() } + .add(intArrayOf(b, c)) + graph.computeIfAbsent(b) { _: Int -> ArrayList() } + .add(intArrayOf(a, c)) + } + val costs: MutableList = ArrayList() + val last: MutableMap = HashMap() + dfs(0, 0, -1, ArrayList(mutableListOf(0, 0)), nums, graph, costs, last, ans) + return ans + } + + private fun dfs( + node: Int, + currCost: Int, + prev: Int, + left: MutableList, + nums: IntArray, + graph: MutableMap>, + costs: MutableList, + last: MutableMap, + ans: IntArray, + ) { + val nodeColorIndexPrev: Int = last.getOrDefault(nums[node], -1) + last.put(nums[node], costs.size) + costs.add(currCost) + val diff = currCost - costs[left[0]] + val length = costs.size - left[0] + if (diff > ans[0] || (diff == ans[0] && length < ans[1])) { + ans[0] = diff + ans[1] = length + } + for (next in graph.getOrDefault(node, ArrayList())) { + val nextNode = next[0] + val nextCost = next[1] + if (nextNode == prev) { + continue + } + val nextLeft: MutableList = ArrayList(left) + if (last.containsKey(nums[nextNode])) { + nextLeft.add(last[nums[nextNode]]!! + 1) + } + nextLeft.sortWith(Comparator.naturalOrder()) + while (nextLeft.size > 2) { + nextLeft.removeAt(0) + } + dfs(nextNode, currCost + nextCost, node, nextLeft, nums, graph, costs, last, ans) + } + last.put(nums[node], nodeColorIndexPrev) + costs.removeAt(costs.size - 1) + } +} diff --git a/src/main/kotlin/g3401_3500/s3486_longest_special_path_ii/readme.md b/src/main/kotlin/g3401_3500/s3486_longest_special_path_ii/readme.md new file mode 100644 index 000000000..b623d0577 --- /dev/null +++ b/src/main/kotlin/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/kotlin/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/Solution.kt b/src/main/kotlin/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/Solution.kt new file mode 100644 index 000000000..168342bb7 --- /dev/null +++ b/src/main/kotlin/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/Solution.kt @@ -0,0 +1,22 @@ +package g3401_3500.s3487_maximum_unique_subarray_sum_after_deletion + +// #Easy #Array #Hash_Table #Greedy #2025_03_16_Time_4_ms_(100.00%)_Space_43.27_MB_(100.00%) + +class Solution { + fun maxSum(nums: IntArray): Int { + var sum = 0 + val st = mutableSetOf() + var mxNeg = Int.MIN_VALUE + for (num in nums) { + if (num > 0) { + st.add(num) + } else { + mxNeg = maxOf(mxNeg, num) + } + } + for (value in st) { + sum += value + } + return if (st.isNotEmpty()) sum else mxNeg + } +} diff --git a/src/main/kotlin/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/readme.md b/src/main/kotlin/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/readme.md new file mode 100644 index 000000000..8568b7a23 --- /dev/null +++ b/src/main/kotlin/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/kotlin/g3401_3500/s3488_closest_equal_element_queries/Solution.kt b/src/main/kotlin/g3401_3500/s3488_closest_equal_element_queries/Solution.kt new file mode 100644 index 000000000..345966f1e --- /dev/null +++ b/src/main/kotlin/g3401_3500/s3488_closest_equal_element_queries/Solution.kt @@ -0,0 +1,37 @@ +package g3401_3500.s3488_closest_equal_element_queries + +// #Medium #Array #Hash_Table #Binary_Search +// #2025_03_16_Time_93_ms_(100.00%)_Space_99.42_MB_(100.00%) + +import kotlin.math.abs +import kotlin.math.min + +class Solution { + fun solveQueries(nums: IntArray, queries: IntArray): List { + val sz = nums.size + val indices: MutableMap> = HashMap>() + for (i in 0.. ArrayList() }.add(i) + } + for (arr in indices.values) { + val m = arr.size + if (m == 1) { + nums[arr[0]] = -1 + continue + } + for (i in 0.. = ArrayList() + for (q in queries) { + res.add(nums[q]) + } + return res + } +} diff --git a/src/main/kotlin/g3401_3500/s3488_closest_equal_element_queries/readme.md b/src/main/kotlin/g3401_3500/s3488_closest_equal_element_queries/readme.md new file mode 100644 index 000000000..aa812bd8f --- /dev/null +++ b/src/main/kotlin/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/kotlin/g3401_3500/s3489_zero_array_transformation_iv/Solution.kt b/src/main/kotlin/g3401_3500/s3489_zero_array_transformation_iv/Solution.kt new file mode 100644 index 000000000..67a3895e9 --- /dev/null +++ b/src/main/kotlin/g3401_3500/s3489_zero_array_transformation_iv/Solution.kt @@ -0,0 +1,40 @@ +package g3401_3500.s3489_zero_array_transformation_iv + +// #Medium #Array #Dynamic_Programming #2025_03_16_Time_104_ms_(100.00%)_Space_73.10_MB_(100.00%) + +import kotlin.math.max +import kotlin.math.min + +class Solution { + private fun solve(q: Array, i: Int, target: Int, k: Int, dp: Array): Int { + // 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.size || target < 0) { + return q.size + 1 + } + if (dp[target][k] != -1) { + return dp[target][k] + } + // skip current query val + var 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 = min(res, solve(q, i, target - q[k][2], k + 1, dp)) + } + dp[target][k] = res + return res + } + + fun minZeroArray(nums: IntArray, queries: Array): Int { + var ans = -1 + for (i in nums.indices) { + val dp = Array(nums[i] + 1) { IntArray(queries.size) } + dp.forEach { row: IntArray -> row.fill(-1) } + ans = max(ans, solve(queries, i, nums[i], 0, dp)) + } + return if (ans > queries.size) -1 else ans + } +} diff --git a/src/main/kotlin/g3401_3500/s3489_zero_array_transformation_iv/readme.md b/src/main/kotlin/g3401_3500/s3489_zero_array_transformation_iv/readme.md new file mode 100644 index 000000000..a516f13c8 --- /dev/null +++ b/src/main/kotlin/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/kotlin/g3401_3500/s3490_count_beautiful_numbers/Solution.kt b/src/main/kotlin/g3401_3500/s3490_count_beautiful_numbers/Solution.kt new file mode 100644 index 000000000..24e820d04 --- /dev/null +++ b/src/main/kotlin/g3401_3500/s3490_count_beautiful_numbers/Solution.kt @@ -0,0 +1,64 @@ +package g3401_3500.s3490_count_beautiful_numbers + +// #Hard #Dynamic_Programming #2025_03_16_Time_246_ms_(100.00%)_Space_61.00_MB_(100.00%) + +class Solution { + fun beautifulNumbers(l: Int, r: Int): Int { + return countBeautiful(r) - countBeautiful(l - 1) + } + + private fun countBeautiful(x: Int): Int { + val digits = getCharArray(x) + val dp = HashMap() + return solve(0, 1, 0, 1, digits, dp) + } + + private fun getCharArray(x: Int): CharArray { + val str = x.toString() + return str.toCharArray() + } + + private fun solve( + i: Int, + tight: Int, + sum: Int, + prod: Int, + digits: CharArray, + dp: HashMap, + ): Int { + if (i == digits.size) { + return if (sum > 0 && prod % sum == 0) { + 1 + } else { + 0 + } + } + val str = "$i - $tight - $sum - $prod" + if (dp.containsKey(str)) { + return dp[str]!! + } + val limit: Int = if (tight == 1) { + digits[i].code - '0'.code + } else { + 9 + } + var count = 0 + var j = 0 + while (j <= limit) { + var newTight = 0 + if (tight == 1 && j == limit) { + newTight = 1 + } + val newSum = sum + j + val newProd: Int = if (j == 0 && sum == 0) { + 1 + } else { + prod * j + } + count += solve(i + 1, newTight, newSum, newProd, digits, dp) + j++ + } + dp.put(str, count) + return count + } +} diff --git a/src/main/kotlin/g3401_3500/s3490_count_beautiful_numbers/readme.md b/src/main/kotlin/g3401_3500/s3490_count_beautiful_numbers/readme.md new file mode 100644 index 000000000..123c58616 --- /dev/null +++ b/src/main/kotlin/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/kotlin/g3401_3500/s3483_unique_3_digit_even_numbers/SolutionTest.kt b/src/test/kotlin/g3401_3500/s3483_unique_3_digit_even_numbers/SolutionTest.kt new file mode 100644 index 000000000..3f8f890ad --- /dev/null +++ b/src/test/kotlin/g3401_3500/s3483_unique_3_digit_even_numbers/SolutionTest.kt @@ -0,0 +1,27 @@ +package g3401_3500.s3483_unique_3_digit_even_numbers + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun totalNumbers() { + assertThat(Solution().totalNumbers(intArrayOf(1, 2, 3, 4)), equalTo(12)) + } + + @Test + fun totalNumbers2() { + assertThat(Solution().totalNumbers(intArrayOf(0, 2, 2)), equalTo(2)) + } + + @Test + fun totalNumbers3() { + assertThat(Solution().totalNumbers(intArrayOf(6, 6, 6)), equalTo(1)) + } + + @Test + fun totalNumbers4() { + assertThat(Solution().totalNumbers(intArrayOf(1, 3, 5)), equalTo(0)) + } +} diff --git a/src/test/kotlin/g3401_3500/s3484_design_spreadsheet/SpreadsheetTest.kt b/src/test/kotlin/g3401_3500/s3484_design_spreadsheet/SpreadsheetTest.kt new file mode 100644 index 000000000..cbeabf3f0 --- /dev/null +++ b/src/test/kotlin/g3401_3500/s3484_design_spreadsheet/SpreadsheetTest.kt @@ -0,0 +1,27 @@ +package g3401_3500.s3484_design_spreadsheet + +import org.hamcrest.CoreMatchers +import org.hamcrest.MatcherAssert +import org.junit.jupiter.api.Test + +internal class SpreadsheetTest { + @Test + fun spreadsheet() { + // Initializes a spreadsheet with 3 rows and 26 columns + val spreadsheet = Spreadsheet(3) + // returns 12 (5+7) + MatcherAssert.assertThat(spreadsheet.getValue("=5+7"), CoreMatchers.equalTo(12)) + // sets A1 to 10 + spreadsheet.setCell("A1", 10) + // returns 16 (10+6) + MatcherAssert.assertThat(spreadsheet.getValue("=A1+6"), CoreMatchers.equalTo(16)) + // sets B2 to 15 + spreadsheet.setCell("B2", 15) + // returns 25 (10+15) + MatcherAssert.assertThat(spreadsheet.getValue("=A1+B2"), CoreMatchers.equalTo(25)) + // resets A1 to 0 + spreadsheet.resetCell("A1") + // returns 15 (0+15) + MatcherAssert.assertThat(spreadsheet.getValue("=A1+B2"), CoreMatchers.equalTo(15)) + } +} diff --git a/src/test/kotlin/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/SolutionTest.kt b/src/test/kotlin/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/SolutionTest.kt new file mode 100644 index 000000000..37647cb54 --- /dev/null +++ b/src/test/kotlin/g3401_3500/s3485_longest_common_prefix_of_k_strings_after_removal/SolutionTest.kt @@ -0,0 +1,32 @@ +package g3401_3500.s3485_longest_common_prefix_of_k_strings_after_removal + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun longestCommonPrefix() { + assertThat( + Solution() + .longestCommonPrefix(arrayOf("jump", "run", "run", "jump", "run"), 2), + equalTo(intArrayOf(3, 4, 4, 3, 4)), + ) + } + + @Test + fun longestCommonPrefix2() { + assertThat( + Solution().longestCommonPrefix(arrayOf("dog", "racer", "car"), 2), + equalTo(intArrayOf(0, 0, 0)), + ) + } + + @Test + fun longestCommonPrefix3() { + assertThat( + Solution().longestCommonPrefix(arrayOf("cdbff"), 1), + equalTo(intArrayOf(0)), + ) + } +} diff --git a/src/test/kotlin/g3401_3500/s3486_longest_special_path_ii/SolutionTest.kt b/src/test/kotlin/g3401_3500/s3486_longest_special_path_ii/SolutionTest.kt new file mode 100644 index 000000000..2b59f722a --- /dev/null +++ b/src/test/kotlin/g3401_3500/s3486_longest_special_path_ii/SolutionTest.kt @@ -0,0 +1,52 @@ +package g3401_3500.s3486_longest_special_path_ii + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun longestSpecialPath() { + assertThat( + Solution() + .longestSpecialPath( + arrayOf( + intArrayOf(0, 1, 1), + intArrayOf(1, 2, 3), + intArrayOf(1, 3, 1), + intArrayOf(2, 4, 6), + intArrayOf(4, 7, 2), + intArrayOf(3, 5, 2), + intArrayOf(3, 6, 5), + intArrayOf(6, 8, 3), + ), + intArrayOf(1, 1, 0, 3, 1, 2, 1, 1, 0), + ), + equalTo(intArrayOf(9, 3)), + ) + } + + @Test + fun longestSpecialPath2() { + assertThat( + Solution() + .longestSpecialPath( + arrayOf(intArrayOf(1, 0, 3), intArrayOf(0, 2, 4), intArrayOf(0, 3, 5)), + intArrayOf(1, 1, 0, 2), + ), + equalTo(intArrayOf(5, 2)), + ) + } + + @Test + fun longestSpecialPath3() { + assertThat( + Solution() + .longestSpecialPath( + arrayOf(intArrayOf(0, 2, 4), intArrayOf(1, 2, 10), intArrayOf(3, 1, 5)), + intArrayOf(4, 5, 4, 5), + ), + equalTo(intArrayOf(15, 3)), + ) + } +} diff --git a/src/test/kotlin/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/SolutionTest.kt b/src/test/kotlin/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/SolutionTest.kt new file mode 100644 index 000000000..e5d400b20 --- /dev/null +++ b/src/test/kotlin/g3401_3500/s3487_maximum_unique_subarray_sum_after_deletion/SolutionTest.kt @@ -0,0 +1,30 @@ +package g3401_3500.s3487_maximum_unique_subarray_sum_after_deletion + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun maxSum() { + assertThat(Solution().maxSum(intArrayOf(1, 2, 3, 4, 5)), equalTo(15)) + } + + @Test + fun maxSum2() { + assertThat(Solution().maxSum(intArrayOf(1, 1, 0, 1, 1)), equalTo(1)) + } + + @Test + fun maxSum3() { + assertThat( + Solution().maxSum(intArrayOf(1, 2, -1, -2, 1, 0, -1)), + equalTo(3), + ) + } + + @Test + fun maxSum4() { + assertThat(Solution().maxSum(intArrayOf(-100)), equalTo(-100)) + } +} diff --git a/src/test/kotlin/g3401_3500/s3488_closest_equal_element_queries/SolutionTest.kt b/src/test/kotlin/g3401_3500/s3488_closest_equal_element_queries/SolutionTest.kt new file mode 100644 index 000000000..84fb6df3c --- /dev/null +++ b/src/test/kotlin/g3401_3500/s3488_closest_equal_element_queries/SolutionTest.kt @@ -0,0 +1,23 @@ +package g3401_3500.s3488_closest_equal_element_queries + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun solveQueries() { + assertThat>( + Solution().solveQueries(intArrayOf(1, 3, 1, 4, 1, 3, 2), intArrayOf(0, 3, 5)), + equalTo>(listOf(2, -1, 3)), + ) + } + + @Test + fun solveQueries2() { + assertThat>( + Solution().solveQueries(intArrayOf(1, 2, 3, 4), intArrayOf(0, 1, 2, 3)), + equalTo>(listOf(-1, -1, -1, -1)), + ) + } +} diff --git a/src/test/kotlin/g3401_3500/s3489_zero_array_transformation_iv/SolutionTest.kt b/src/test/kotlin/g3401_3500/s3489_zero_array_transformation_iv/SolutionTest.kt new file mode 100644 index 000000000..6e27acabd --- /dev/null +++ b/src/test/kotlin/g3401_3500/s3489_zero_array_transformation_iv/SolutionTest.kt @@ -0,0 +1,65 @@ +package g3401_3500.s3489_zero_array_transformation_iv + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun minZeroArray() { + assertThat( + Solution() + .minZeroArray( + intArrayOf(2, 0, 2), + arrayOf(intArrayOf(0, 2, 1), intArrayOf(0, 2, 1), intArrayOf(1, 1, 3)), + ), + equalTo(2), + ) + } + + @Test + fun minZeroArray2() { + assertThat( + Solution() + .minZeroArray(intArrayOf(4, 3, 2, 1), arrayOf(intArrayOf(1, 3, 2), intArrayOf(0, 2, 1))), + equalTo(-1), + ) + } + + @Test + fun minZeroArray3() { + assertThat( + Solution() + .minZeroArray( + intArrayOf(1, 2, 3, 2, 1), + arrayOf( + intArrayOf(0, 1, 1), + intArrayOf(1, 2, 1), + intArrayOf(2, 3, 2), + intArrayOf(3, 4, 1), + intArrayOf(4, 4, 1), + ), + ), + equalTo(4), + ) + } + + @Test + fun minZeroArray4() { + assertThat( + Solution() + .minZeroArray( + intArrayOf(1, 2, 3, 2, 6), + arrayOf( + intArrayOf(0, 1, 1), + intArrayOf(0, 2, 1), + intArrayOf(1, 4, 2), + intArrayOf(4, 4, 4), + intArrayOf(3, 4, 1), + intArrayOf(4, 4, 5), + ), + ), + equalTo(4), + ) + } +} diff --git a/src/test/kotlin/g3401_3500/s3490_count_beautiful_numbers/SolutionTest.kt b/src/test/kotlin/g3401_3500/s3490_count_beautiful_numbers/SolutionTest.kt new file mode 100644 index 000000000..e67a87bda --- /dev/null +++ b/src/test/kotlin/g3401_3500/s3490_count_beautiful_numbers/SolutionTest.kt @@ -0,0 +1,25 @@ +package g3401_3500.s3490_count_beautiful_numbers + +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test + +internal class SolutionTest { + @Test + fun beautifulNumbers() { + assertThat(Solution().beautifulNumbers(10, 20), equalTo(2)) + } + + @Test + fun beautifulNumbers2() { + assertThat(Solution().beautifulNumbers(1, 15), equalTo(10)) + } + + @Test + fun beautifulNumbers3() { + assertThat( + Solution().beautifulNumbers(6725, 270910825), + equalTo(178996547), + ) + } +}