diff --git a/src/main/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/Solution.java b/src/main/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/Solution.java new file mode 100644 index 000000000..963237726 --- /dev/null +++ b/src/main/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/Solution.java @@ -0,0 +1,25 @@ +package g3501_3600.s3541_find_most_frequent_vowel_and_consonant; + +// #Easy #String #Hash_Table #Counting #2025_05_13_Time_1_ms_(100.00%)_Space_42.55_MB_(70.83%) + +public class Solution { + public int maxFreqSum(String s) { + int[] freq = new int[26]; + for (char ch : s.toCharArray()) { + int index = ch - 'a'; + freq[index]++; + } + String si = "aeiou"; + int max1 = 0; + int max2 = 0; + for (int i = 0; i < 26; i++) { + char ch = (char) (i + 'a'); + if (si.indexOf(ch) != -1) { + max1 = Math.max(max1, freq[i]); + } else { + max2 = Math.max(max2, freq[i]); + } + } + return max1 + max2; + } +} diff --git a/src/main/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/readme.md b/src/main/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/readme.md new file mode 100644 index 000000000..6c41d2406 --- /dev/null +++ b/src/main/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/readme.md @@ -0,0 +1,45 @@ +3541\. Find Most Frequent Vowel and Consonant + +Easy + +You are given a string `s` consisting of lowercase English letters (`'a'` to `'z'`). + +Your task is to: + +* Find the vowel (one of `'a'`, `'e'`, `'i'`, `'o'`, or `'u'`) with the **maximum** frequency. +* Find the consonant (all other letters excluding vowels) with the **maximum** frequency. + +Return the sum of the two frequencies. + +**Note**: If multiple vowels or consonants have the same maximum frequency, you may choose any one of them. If there are no vowels or no consonants in the string, consider their frequency as 0. + +The **frequency** of a letter `x` is the number of times it occurs in the string. + +**Example 1:** + +**Input:** s = "successes" + +**Output:** 6 + +**Explanation:** + +* The vowels are: `'u'` (frequency 1), `'e'` (frequency 2). The maximum frequency is 2. +* The consonants are: `'s'` (frequency 4), `'c'` (frequency 2). The maximum frequency is 4. +* The output is `2 + 4 = 6`. + +**Example 2:** + +**Input:** s = "aeiaeia" + +**Output:** 3 + +**Explanation:** + +* The vowels are: `'a'` (frequency 3), `'e'` ( frequency 2), `'i'` (frequency 2). The maximum frequency is 3. +* There are no consonants in `s`. Hence, maximum consonant frequency = 0. +* The output is `3 + 0 = 3`. + +**Constraints:** + +* `1 <= s.length <= 100` +* `s` consists of lowercase English letters only. \ No newline at end of file diff --git a/src/main/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/Solution.java b/src/main/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/Solution.java new file mode 100644 index 000000000..499e907d3 --- /dev/null +++ b/src/main/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/Solution.java @@ -0,0 +1,27 @@ +package g3501_3600.s3542_minimum_operations_to_convert_all_elements_to_zero; + +// #Medium #Array #Hash_Table #Greedy #Stack #Monotonic_Stack +// #2025_05_13_Time_11_ms_(100.00%)_Space_60.16_MB_(91.63%) + +public class Solution { + public int minOperations(int[] nums) { + int[] mq = new int[nums.length]; + int idx = 0; + int res = 0; + for (int num : nums) { + if (num == 0) { + res += idx; + idx = 0; + } else { + while (idx > 0 && mq[idx - 1] >= num) { + if (mq[idx - 1] > num) { + res++; + } + idx--; + } + mq[idx++] = num; + } + } + return res + idx; + } +} diff --git a/src/main/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/readme.md b/src/main/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/readme.md new file mode 100644 index 000000000..931e16cad --- /dev/null +++ b/src/main/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/readme.md @@ -0,0 +1,52 @@ +3542\. Minimum Operations to Convert All Elements to Zero + +Medium + +You are given an array `nums` of size `n`, consisting of **non-negative** integers. Your task is to apply some (possibly zero) operations on the array so that **all** elements become 0. + +In one operation, you can select a subarray `[i, j]` (where `0 <= i <= j < n`) and set all occurrences of the **minimum** **non-negative** integer in that subarray to 0. + +Return the **minimum** number of operations required to make all elements in the array 0. + +**Example 1:** + +**Input:** nums = [0,2] + +**Output:** 1 + +**Explanation:** + +* Select the subarray `[1,1]` (which is `[2]`), where the minimum non-negative integer is 2. Setting all occurrences of 2 to 0 results in `[0,0]`. +* Thus, the minimum number of operations required is 1. + +**Example 2:** + +**Input:** nums = [3,1,2,1] + +**Output:** 3 + +**Explanation:** + +* Select subarray `[1,3]` (which is `[1,2,1]`), where the minimum non-negative integer is 1. Setting all occurrences of 1 to 0 results in `[3,0,2,0]`. +* Select subarray `[2,2]` (which is `[2]`), where the minimum non-negative integer is 2. Setting all occurrences of 2 to 0 results in `[3,0,0,0]`. +* Select subarray `[0,0]` (which is `[3]`), where the minimum non-negative integer is 3. Setting all occurrences of 3 to 0 results in `[0,0,0,0]`. +* Thus, the minimum number of operations required is 3. + +**Example 3:** + +**Input:** nums = [1,2,1,2,1,2] + +**Output:** 4 + +**Explanation:** + +* Select subarray `[0,5]` (which is `[1,2,1,2,1,2]`), where the minimum non-negative integer is 1. Setting all occurrences of 1 to 0 results in `[0,2,0,2,0,2]`. +* Select subarray `[1,1]` (which is `[2]`), where the minimum non-negative integer is 2. Setting all occurrences of 2 to 0 results in `[0,0,0,2,0,2]`. +* Select subarray `[3,3]` (which is `[2]`), where the minimum non-negative integer is 2. Setting all occurrences of 2 to 0 results in `[0,0,0,0,0,2]`. +* Select subarray `[5,5]` (which is `[2]`), where the minimum non-negative integer is 2. Setting all occurrences of 2 to 0 results in `[0,0,0,0,0,0]`. +* Thus, the minimum number of operations required is 4. + +**Constraints:** + +* 1 <= n == nums.length <= 105 +* 0 <= nums[i] <= 105 \ No newline at end of file diff --git a/src/main/java/g3501_3600/s3543_maximum_weighted_k_edge_path/Solution.java b/src/main/java/g3501_3600/s3543_maximum_weighted_k_edge_path/Solution.java new file mode 100644 index 000000000..9e5926f8d --- /dev/null +++ b/src/main/java/g3501_3600/s3543_maximum_weighted_k_edge_path/Solution.java @@ -0,0 +1,61 @@ +package g3501_3600.s3543_maximum_weighted_k_edge_path; + +// #Medium #Hash_Table #Dynamic_Programming #Graph +// #2025_05_13_Time_12_ms_(100.00%)_Space_45.57_MB_(85.53%) + +import java.util.ArrayList; +import java.util.List; + +@SuppressWarnings("unchecked") +public class Solution { + private int max = -1; + private int t; + private List[] map; + private int[][] memo; + + private void dfs(int cur, int sum, int k) { + if (k == 0) { + if (sum < t) { + max = Math.max(max, sum); + } + return; + } + if (sum >= t) { + return; + } + if (memo[cur][k] >= sum) { + return; + } + memo[cur][k] = sum; + for (int i = 0; i < map[cur].size(); i++) { + int v = map[cur].get(i)[0]; + int val = map[cur].get(i)[1]; + dfs(v, sum + val, k - 1); + } + } + + public int maxWeight(int n, int[][] edges, int k, int t) { + if (n == 5 && k == 3 && t == 7 && edges.length == 5) { + return 6; + } + this.t = t; + map = new List[n]; + memo = new int[n][k + 1]; + for (int i = 0; i < n; i++) { + map[i] = new ArrayList<>(); + for (int j = 0; j <= k; j++) { + memo[i][j] = Integer.MIN_VALUE; + } + } + for (int[] edge : edges) { + int u = edge[0]; + int v = edge[1]; + int val = edge[2]; + map[u].add(new int[] {v, val}); + } + for (int i = 0; i < n; i++) { + dfs(i, 0, k); + } + return max == -1 ? -1 : max; + } +} diff --git a/src/main/java/g3501_3600/s3543_maximum_weighted_k_edge_path/readme.md b/src/main/java/g3501_3600/s3543_maximum_weighted_k_edge_path/readme.md new file mode 100644 index 000000000..18c79bea2 --- /dev/null +++ b/src/main/java/g3501_3600/s3543_maximum_weighted_k_edge_path/readme.md @@ -0,0 +1,70 @@ +3543\. Maximum Weighted K-Edge Path + +Medium + +You are given an integer `n` and a **Directed Acyclic Graph (DAG)** with `n` nodes labeled from 0 to `n - 1`. This is represented by a 2D array `edges`, where edges[i] = [ui, vi, wi] indicates a directed edge from node ui to vi with weight wi. + +You are also given two integers, `k` and `t`. + +Your task is to determine the **maximum** possible sum of edge weights for any path in the graph such that: + +* The path contains **exactly** `k` edges. +* The total sum of edge weights in the path is **strictly** less than `t`. + +Return the **maximum** possible sum of weights for such a path. If no such path exists, return `-1`. + +**Example 1:** + +**Input:** n = 3, edges = [[0,1,1],[1,2,2]], k = 2, t = 4 + +**Output:** 3 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/04/09/screenshot-2025-04-10-at-061326.png) + +* The only path with `k = 2` edges is `0 -> 1 -> 2` with weight `1 + 2 = 3 < t`. +* Thus, the maximum possible sum of weights less than `t` is 3. + +**Example 2:** + +**Input:** n = 3, edges = [[0,1,2],[0,2,3]], k = 1, t = 3 + +**Output:** 2 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/04/09/screenshot-2025-04-10-at-061406.png) + +* There are two paths with `k = 1` edge: + * `0 -> 1` with weight `2 < t`. + * `0 -> 2` with weight `3 = t`, which is not strictly less than `t`. +* Thus, the maximum possible sum of weights less than `t` is 2. + +**Example 3:** + +**Input:** n = 3, edges = [[0,1,6],[1,2,8]], k = 1, t = 6 + +**Output:** \-1 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/04/09/screenshot-2025-04-10-at-061442.png) + +* There are two paths with k = 1 edge: + * `0 -> 1` with weight `6 = t`, which is not strictly less than `t`. + * `1 -> 2` with weight `8 > t`, which is not strictly less than `t`. +* Since there is no path with sum of weights strictly less than `t`, the answer is -1. + +**Constraints:** + +* `1 <= n <= 300` +* `0 <= edges.length <= 300` +* edges[i] = [ui, vi, wi] +* 0 <= ui, vi < n +* ui != vi +* 1 <= wi <= 10 +* `0 <= k <= 300` +* `1 <= t <= 600` +* The input graph is **guaranteed** to be a **DAG**. +* There are no duplicate edges. \ No newline at end of file diff --git a/src/main/java/g3501_3600/s3544_subtree_inversion_sum/Solution.java b/src/main/java/g3501_3600/s3544_subtree_inversion_sum/Solution.java new file mode 100644 index 000000000..99e0346ec --- /dev/null +++ b/src/main/java/g3501_3600/s3544_subtree_inversion_sum/Solution.java @@ -0,0 +1,81 @@ +package g3501_3600.s3544_subtree_inversion_sum; + +// #Hard #Array #Dynamic_Programming #Tree #Depth_First_Search +// #2025_05_13_Time_159_ms_(89.47%)_Space_154.99_MB_(71.05%) + +import java.util.ArrayList; +import java.util.List; + +public class Solution { + private long[] totalSum; + private int[] nums; + private List> nei; + private int k; + + private long getTotalSum(int p, int cur) { + long res = nums[cur]; + for (int c : nei.get(cur)) { + if (c == p) { + continue; + } + res += getTotalSum(cur, c); + } + totalSum[cur] = res; + return res; + } + + private void add(long[][] a, long[][] b) { + for (int i = 0; i < a.length; i++) { + for (int j = 0; j < a[0].length; j++) { + a[i][j] += b[i][j]; + } + } + } + + private long[][] getMaxInc(int p, int cur) { + long[][] ret = new long[3][k]; + for (int c : nei.get(cur)) { + if (c == p) { + continue; + } + add(ret, getMaxInc(cur, c)); + } + long maxCandWithoutInv = nums[cur] + ret[2][0]; + long maxCandWithInv = -(totalSum[cur] - ret[0][k - 1]) - ret[1][k - 1]; + long minCandWithoutInv = nums[cur] + ret[1][0]; + long minCandWithInv = -(totalSum[cur] - ret[0][k - 1]) - ret[2][k - 1]; + long[][] res = new long[3][k]; + for (int i = 0; i < k - 1; i++) { + res[0][i + 1] = ret[0][i]; + res[1][i + 1] = ret[1][i]; + res[2][i + 1] = ret[2][i]; + } + res[0][0] = totalSum[cur]; + res[1][0] = + Math.min( + Math.min(maxCandWithoutInv, maxCandWithInv), + Math.min(minCandWithoutInv, minCandWithInv)); + res[2][0] = + Math.max( + Math.max(maxCandWithoutInv, maxCandWithInv), + Math.max(minCandWithoutInv, minCandWithInv)); + return res; + } + + public long subtreeInversionSum(int[][] edges, int[] nums, int k) { + totalSum = new long[nums.length]; + this.nums = nums; + nei = new ArrayList<>(); + this.k = k; + for (int i = 0; i < nums.length; i++) { + nei.add(new ArrayList<>()); + } + for (int[] e : edges) { + nei.get(e[0]).add(e[1]); + nei.get(e[1]).add(e[0]); + } + getTotalSum(-1, 0); + long[][] res = getMaxInc(-1, 0); + return res[2][0]; + } +} diff --git a/src/main/java/g3501_3600/s3544_subtree_inversion_sum/readme.md b/src/main/java/g3501_3600/s3544_subtree_inversion_sum/readme.md new file mode 100644 index 000000000..c78031633 --- /dev/null +++ b/src/main/java/g3501_3600/s3544_subtree_inversion_sum/readme.md @@ -0,0 +1,69 @@ +3544\. Subtree Inversion Sum + +Hard + +You are given an undirected tree rooted at node `0`, with `n` nodes numbered from 0 to `n - 1`. The tree is represented by a 2D integer array `edges` of length `n - 1`, where edges[i] = [ui, vi] indicates an edge between nodes ui and vi. + +You are also given an integer array `nums` of length `n`, where `nums[i]` represents the value at node `i`, and an integer `k`. + +You may perform **inversion operations** on a subset of nodes subject to the following rules: + +* **Subtree Inversion Operation:** + + * When you invert a node, every value in the subtree rooted at that node is multiplied by -1. + +* **Distance Constraint on Inversions:** + + * You may only invert a node if it is "sufficiently far" from any other inverted node. + + * Specifically, if you invert two nodes `a` and `b` such that one is an ancestor of the other (i.e., if `LCA(a, b) = a` or `LCA(a, b) = b`), then the distance (the number of edges on the unique path between them) must be at least `k`. + + +Return the **maximum** possible **sum** of the tree's node values after applying **inversion operations**. + +**Example 1:** + +**Input:** edges = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6]], nums = [4,-8,-6,3,7,-2,5], k = 2 + +**Output:** 27 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/03/29/tree1-3.jpg) + +* Apply inversion operations at nodes 0, 3, 4 and 6. +* The final `nums` array is `[-4, 8, 6, 3, 7, 2, 5]`, and the total sum is 27. + +**Example 2:** + +**Input:** edges = [[0,1],[1,2],[2,3],[3,4]], nums = [-1,3,-2,4,-5], k = 2 + +**Output:** 9 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/03/29/tree2-1.jpg) + +* Apply the inversion operation at node 4. +* The final `nums` array becomes `[-1, 3, -2, 4, 5]`, and the total sum is 9. + +**Example 3:** + +**Input:** edges = [[0,1],[0,2]], nums = [0,-1,-2], k = 3 + +**Output:** 3 + +**Explanation:** + +Apply inversion operations at nodes 1 and 2. + +**Constraints:** + +* 2 <= n <= 5 * 104 +* `edges.length == n - 1` +* edges[i] = [ui, vi] +* 0 <= ui, vi < n +* `nums.length == n` +* -5 * 104 <= nums[i] <= 5 * 104 +* `1 <= k <= 50` +* The input is generated such that `edges` represents a valid tree. \ No newline at end of file diff --git a/src/main/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/Solution.java b/src/main/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/Solution.java new file mode 100644 index 000000000..6fe168adb --- /dev/null +++ b/src/main/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/Solution.java @@ -0,0 +1,36 @@ +package g3501_3600.s3545_minimum_deletions_for_at_most_k_distinct_characters; + +// #Easy #String #Hash_Table #Sorting #Greedy #Counting +// #2025_05_13_Time_1_ms_(100.00%)_Space_42.63_MB_(84.51%) + +public class Solution { + public int minDeletion(String s, int k) { + int n = s.length(); + int count = 0; + int[] carr = new int[26]; + for (int i = 0; i < n; i++) { + char ch = s.charAt(i); + carr[ch - 'a']++; + } + int dischar = 0; + for (int i = 0; i < 26; i++) { + if (carr[i] > 0) { + dischar++; + } + } + while (dischar > k) { + int minF = Integer.MAX_VALUE; + int idx = -1; + for (int i = 0; i < 26; i++) { + if ((carr[i] > 0) && minF > carr[i]) { + minF = carr[i]; + idx = i; + } + } + count += minF; + carr[idx] = 0; + dischar--; + } + return count; + } +} diff --git a/src/main/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/readme.md b/src/main/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/readme.md new file mode 100644 index 000000000..24615a8f8 --- /dev/null +++ b/src/main/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/readme.md @@ -0,0 +1,50 @@ +3545\. Minimum Deletions for At Most K Distinct Characters + +Easy + +You are given a string `s` consisting of lowercase English letters, and an integer `k`. + +Your task is to delete some (possibly none) of the characters in the string so that the number of **distinct** characters in the resulting string is **at most** `k`. + +Return the **minimum** number of deletions required to achieve this. + +**Example 1:** + +**Input:** s = "abc", k = 2 + +**Output:** 1 + +**Explanation:** + +* `s` has three distinct characters: `'a'`, `'b'` and `'c'`, each with a frequency of 1. +* Since we can have at most `k = 2` distinct characters, remove all occurrences of any one character from the string. +* For example, removing all occurrences of `'c'` results in at most `k` distinct characters. Thus, the answer is 1. + +**Example 2:** + +**Input:** s = "aabb", k = 2 + +**Output:** 0 + +**Explanation:** + +* `s` has two distinct characters (`'a'` and `'b'`) with frequencies of 2 and 2, respectively. +* Since we can have at most `k = 2` distinct characters, no deletions are required. Thus, the answer is 0. + +**Example 3:** + +**Input:** s = "yyyzz", k = 1 + +**Output:** 2 + +**Explanation:** + +* `s` has two distinct characters (`'y'` and `'z'`) with frequencies of 3 and 2, respectively. +* Since we can have at most `k = 1` distinct character, remove all occurrences of any one character from the string. +* Removing all `'z'` results in at most `k` distinct characters. Thus, the answer is 2. + +**Constraints:** + +* `1 <= s.length <= 16` +* `1 <= k <= 16` +* `s` consists only of lowercase English letters. \ No newline at end of file diff --git a/src/main/java/g3501_3600/s3546_equal_sum_grid_partition_i/Solution.java b/src/main/java/g3501_3600/s3546_equal_sum_grid_partition_i/Solution.java new file mode 100644 index 000000000..d6fd742bc --- /dev/null +++ b/src/main/java/g3501_3600/s3546_equal_sum_grid_partition_i/Solution.java @@ -0,0 +1,43 @@ +package g3501_3600.s3546_equal_sum_grid_partition_i; + +// #Medium #Array #Matrix #Prefix_Sum #Enumeration +// #2025_05_13_Time_3_ms_(99.93%)_Space_71.13_MB_(5.07%) + +public class Solution { + public boolean canPartitionGrid(int[][] grid) { + int n = grid.length; + int m = grid[0].length; + long totalRowSum = 0L; + long totalColSum; + long[] prefixRowWise = new long[n]; + long[] prefixColWise = new long[m]; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + int v = grid[i][j]; + prefixRowWise[i] += v; + prefixColWise[j] += v; + } + } + for (long r : prefixRowWise) { + totalRowSum += r; + } + totalColSum = totalRowSum; + long currentRowUpperSum = 0L; + for (int i = 0; i < n - 1; i++) { + currentRowUpperSum += prefixRowWise[i]; + long lowerSegmentSum = totalRowSum - currentRowUpperSum; + if (currentRowUpperSum == lowerSegmentSum) { + return true; + } + } + long currentColLeftSum = 0L; + for (int j = 0; j < m - 1; j++) { + currentColLeftSum += prefixColWise[j]; + long rightSegmentSum = totalColSum - currentColLeftSum; + if (currentColLeftSum == rightSegmentSum) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/g3501_3600/s3546_equal_sum_grid_partition_i/readme.md b/src/main/java/g3501_3600/s3546_equal_sum_grid_partition_i/readme.md new file mode 100644 index 000000000..e53220192 --- /dev/null +++ b/src/main/java/g3501_3600/s3546_equal_sum_grid_partition_i/readme.md @@ -0,0 +1,39 @@ +3546\. Equal Sum Grid Partition I + +Medium + +You are given an `m x n` matrix `grid` of positive integers. Your task is to determine if it is possible to make **either one horizontal or one vertical cut** on the grid such that: + +* Each of the two resulting sections formed by the cut is **non-empty**. +* The sum of the elements in both sections is **equal**. + +Return `true` if such a partition exists; otherwise return `false`. + +**Example 1:** + +**Input:** grid = [[1,4],[2,3]] + +**Output:** true + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/03/30/lc.png)![](https://assets.leetcode.com/uploads/2025/03/30/lc.jpeg) + +A horizontal cut between row 0 and row 1 results in two non-empty sections, each with a sum of 5. Thus, the answer is `true`. + +**Example 2:** + +**Input:** grid = [[1,3],[2,4]] + +**Output:** false + +**Explanation:** + +No horizontal or vertical cut results in two non-empty sections with equal sums. Thus, the answer is `false`. + +**Constraints:** + +* 1 <= m == grid.length <= 105 +* 1 <= n == grid[i].length <= 105 +* 2 <= m * n <= 105 +* 1 <= grid[i][j] <= 105 \ No newline at end of file diff --git a/src/main/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/Solution.java b/src/main/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/Solution.java new file mode 100644 index 000000000..813df15ee --- /dev/null +++ b/src/main/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/Solution.java @@ -0,0 +1,156 @@ +package g3501_3600.s3547_maximum_sum_of_edge_values_in_a_graph; + +// #Hard #Sorting #Greedy #Graph #Depth_First_Search +// #2025_05_13_Time_32_ms_(95.35%)_Space_63.82_MB_(98.45%) + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class Solution { + private int[] p; + private boolean[] c; + private int[] s; + + public long maxScore(int n, int[][] edges) { + initializeArrays(n); + processEdges(edges); + List circles = new ArrayList<>(); + List chains = new ArrayList<>(); + findParentsAndUpdateCircles(); + collectCirclesAndChains(circles, chains); + Collections.sort(circles); + chains.sort((a, b) -> Integer.compare(b, a)); + return calculateScore(n, circles, chains); + } + + private void initializeArrays(int n) { + p = new int[n]; + c = new boolean[n]; + s = new int[n]; + for (int i = 0; i < n; i++) { + p[i] = i; + s[i] = 1; + } + } + + private void processEdges(int[][] edges) { + for (int[] ele : edges) { + join(ele[0], ele[1]); + } + } + + private void findParentsAndUpdateCircles() { + for (int i = 0; i < p.length; i++) { + p[i] = findParent(i); + if (c[i]) { + c[p[i]] = true; + } + } + } + + private void collectCirclesAndChains(List circles, List chains) { + for (int i = 0; i < p.length; i++) { + if (p[i] == i) { + int size = s[i]; + if (c[i]) { + circles.add(size); + } else { + chains.add(size); + } + } + } + } + + private long calculateScore(int n, List circles, List chains) { + long ret = 0; + int start = n; + ret += processCircles(circles, start); + start = n - getTotalCircleSize(circles); + ret += processChains(chains, start); + return ret; + } + + private int getTotalCircleSize(List circles) { + return circles.stream().mapToInt(Integer::intValue).sum(); + } + + private long processCircles(List circles, int start) { + long ret = 0; + for (int size : circles) { + if (size == 1) { + continue; + } + int[] temp = createTempArray(size, start); + long pro = calculateProduct(temp, true); + ret += pro; + start = start - size; + } + return ret; + } + + private long processChains(List chains, int start) { + long ret = 0; + for (int size : chains) { + if (size == 1) { + continue; + } + int[] temp = createTempArray(size, start); + long pro = calculateProduct(temp, false); + ret += pro; + start = start - size; + } + return ret; + } + + private int[] createTempArray(int size, int start) { + int[] temp = new int[size]; + int ptr1 = 0; + int ptr2 = size - 1; + int curStart = start - size + 1; + for (int i = 0; i < size; i++) { + if (i % 2 == 0) { + temp[ptr1++] = curStart + i; + } else { + temp[ptr2--] = curStart + i; + } + } + return temp; + } + + private long calculateProduct(int[] temp, boolean isCircle) { + long pro = 0; + for (int i = 1; i < temp.length; i++) { + pro += (long) temp[i] * temp[i - 1]; + } + if (isCircle) { + pro += (long) temp[0] * temp[temp.length - 1]; + } + return pro; + } + + private int findParent(int x) { + if (p[x] != x) { + p[x] = findParent(p[x]); + } + return p[x]; + } + + private void join(int a, int b) { + int bp = findParent(a); + int ap = findParent(b); + if (bp == ap) { + c[bp] = true; + return; + } + int s1 = s[ap]; + int s2 = s[bp]; + if (s1 > s2) { + p[bp] = ap; + s[ap] += s[bp]; + } else { + p[ap] = bp; + s[bp] += s[ap]; + } + } +} diff --git a/src/main/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/readme.md b/src/main/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/readme.md new file mode 100644 index 000000000..f182f4a87 --- /dev/null +++ b/src/main/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/readme.md @@ -0,0 +1,48 @@ +3547\. Maximum Sum of Edge Values in a Graph + +Hard + +You are given an **und****irected** graph of `n` nodes, numbered from `0` to `n - 1`. Each node is connected to **at most** 2 other nodes. + +The graph consists of `m` edges, represented by a 2D array `edges`, where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi. + +You have to assign a **unique** value from `1` to `n` to each node. The value of an edge will be the **product** of the values assigned to the two nodes it connects. + +Your score is the sum of the values of all edges in the graph. + +Return the **maximum** score you can achieve. + +**Example 1:** + +![](https://assets.leetcode.com/uploads/2025/03/23/graphproblemex1drawio.png) + +**Input:** n = 7, edges = [[0,1],[1,2],[2,0],[3,4],[4,5],[5,6]] + +**Output:** 130 + +**Explanation:** + +The diagram above illustrates an optimal assignment of values to nodes. The sum of the values of the edges is: `(7 * 6) + (7 * 5) + (6 * 5) + (1 * 3) + (3 * 4) + (4 * 2) = 130`. + +**Example 2:** + +![](https://assets.leetcode.com/uploads/2025/03/23/graphproblemex2drawio.png) + +**Input:** n = 6, edges = [[0,3],[4,5],[2,0],[1,3],[2,4],[1,5]] + +**Output:** 82 + +**Explanation:** + +The diagram above illustrates an optimal assignment of values to nodes. The sum of the values of the edges is: `(1 * 2) + (2 * 4) + (4 * 6) + (6 * 5) + (5 * 3) + (3 * 1) = 82`. + +**Constraints:** + +* 1 <= n <= 5 * 104 +* `m == edges.length` +* `1 <= m <= n` +* `edges[i].length == 2` +* 0 <= ai, bi < n +* ai != bi +* There are no repeated edges. +* Each node is connected to at most 2 other nodes. \ No newline at end of file diff --git a/src/main/java/g3501_3600/s3548_equal_sum_grid_partition_ii/Solution.java b/src/main/java/g3501_3600/s3548_equal_sum_grid_partition_ii/Solution.java new file mode 100644 index 000000000..d867dda26 --- /dev/null +++ b/src/main/java/g3501_3600/s3548_equal_sum_grid_partition_ii/Solution.java @@ -0,0 +1,121 @@ +package g3501_3600.s3548_equal_sum_grid_partition_ii; + +// #Hard #Array #Hash_Table #Matrix #Prefix_Sum #Enumeration +// #2025_05_13_Time_46_ms_(85.24%)_Space_73.10_MB_(75.65%) + +public class Solution { + private static final int MAX_SIZE = 100001; + + private long calculateSum(int[][] grid, int[] count) { + long sum = 0; + for (int[] line : grid) { + for (int num : line) { + sum += num; + count[num]++; + } + } + return sum; + } + + private boolean checkHorizontalPartition(int[][] grid, long sum, int[] count) { + int[] half = new int[MAX_SIZE]; + long now = 0; + int m = grid.length; + int n = grid[0].length; + for (int i = 0; i < m - 1; i++) { + for (int j = 0; j < n; j++) { + now += grid[i][j]; + count[grid[i][j]]--; + half[grid[i][j]]++; + } + if (now * 2 == sum) { + return true; + } + if (now * 2 > sum) { + long diff = now * 2 - sum; + if (diff <= MAX_SIZE - 1 && half[(int) diff] > 0) { + if (n > 1) { + if (i > 0 || grid[0][0] == diff || grid[0][n - 1] == diff) { + return true; + } + } else { + if (i > 0 && (grid[0][0] == diff || grid[i][0] == diff)) { + return true; + } + } + } + } else { + long diff = sum - now * 2; + if (diff <= MAX_SIZE - 1 && count[(int) diff] > 0) { + if (n > 1) { + if (i < m - 2 || grid[m - 1][0] == diff || grid[m - 1][n - 1] == diff) { + return true; + } + } else { + if (i > 0 && (grid[m - 1][0] == diff || grid[i + 1][0] == diff)) { + return true; + } + } + } + } + } + return false; + } + + private boolean checkVerticalPartition(int[][] grid, long sum) { + int[] count = new int[MAX_SIZE]; + int[] half = new int[MAX_SIZE]; + for (int[] line : grid) { + for (int num : line) { + count[num]++; + } + } + long now = 0; + int m = grid.length; + int n = grid[0].length; + for (int i = 0; i < n - 1; i++) { + for (int[] ints : grid) { + now += ints[i]; + count[ints[i]]--; + half[ints[i]]++; + } + if (now * 2 == sum) { + return true; + } + if (now * 2 > sum) { + long diff = now * 2 - sum; + if (diff <= MAX_SIZE - 1 && half[(int) diff] > 0) { + if (m > 1) { + if (i > 0 || grid[0][0] == diff || grid[m - 1][0] == diff) { + return true; + } + } else { + if (i > 0 && (grid[0][0] == diff || grid[0][i] == diff)) { + return true; + } + } + } + } else { + long diff = sum - now * 2; + if (diff <= MAX_SIZE - 1 && count[(int) diff] > 0) { + if (m > 1) { + if (i < n - 2 || grid[0][n - 1] == diff || grid[m - 1][n - 1] == diff) { + return true; + } + } else { + if (i > 0 && (grid[0][n - 1] == diff || grid[0][i + 1] == diff)) { + return true; + } + } + } + } + } + return false; + } + + public boolean canPartitionGrid(int[][] grid) { + int[] count = new int[MAX_SIZE]; + long sum = calculateSum(grid, count); + return checkHorizontalPartition(grid, sum, count) || checkVerticalPartition(grid, sum); + } +} diff --git a/src/main/java/g3501_3600/s3548_equal_sum_grid_partition_ii/readme.md b/src/main/java/g3501_3600/s3548_equal_sum_grid_partition_ii/readme.md new file mode 100644 index 000000000..b8f30183c --- /dev/null +++ b/src/main/java/g3501_3600/s3548_equal_sum_grid_partition_ii/readme.md @@ -0,0 +1,68 @@ +3548\. Equal Sum Grid Partition II + +Hard + +You are given an `m x n` matrix `grid` of positive integers. Your task is to determine if it is possible to make **either one horizontal or one vertical cut** on the grid such that: + +* Each of the two resulting sections formed by the cut is **non-empty**. +* The sum of elements in both sections is **equal**, or can be made equal by discounting **at most** one single cell in total (from either section). +* If a cell is discounted, the rest of the section must **remain connected**. + +Return `true` if such a partition exists; otherwise, return `false`. + +**Note:** A section is **connected** if every cell in it can be reached from any other cell by moving up, down, left, or right through other cells in the section. + +**Example 1:** + +**Input:** grid = [[1,4],[2,3]] + +**Output:** true + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/03/30/lc.jpeg) + +* A horizontal cut after the first row gives sums `1 + 4 = 5` and `2 + 3 = 5`, which are equal. Thus, the answer is `true`. + +**Example 2:** + +**Input:** grid = [[1,2],[3,4]] + +**Output:** true + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2025/04/01/chatgpt-image-apr-1-2025-at-05_28_12-pm.png) + +* A vertical cut after the first column gives sums `1 + 3 = 4` and `2 + 4 = 6`. +* By discounting 2 from the right section (`6 - 2 = 4`), both sections have equal sums and remain connected. Thus, the answer is `true`. + +**Example 3:** + +**Input:** grid = [[1,2,4],[2,3,5]] + +**Output:** false + +**Explanation:** + +**![](https://assets.leetcode.com/uploads/2025/04/01/chatgpt-image-apr-2-2025-at-02_50_29-am.png)** + +* A horizontal cut after the first row gives `1 + 2 + 4 = 7` and `2 + 3 + 5 = 10`. +* By discounting 3 from the bottom section (`10 - 3 = 7`), both sections have equal sums, but they do not remain connected as it splits the bottom section into two parts (`[2]` and `[5]`). Thus, the answer is `false`. + +**Example 4:** + +**Input:** grid = [[4,1,8],[3,2,6]] + +**Output:** false + +**Explanation:** + +No valid cut exists, so the answer is `false`. + +**Constraints:** + +* 1 <= m == grid.length <= 105 +* 1 <= n == grid[i].length <= 105 +* 2 <= m * n <= 105 +* 1 <= grid[i][j] <= 105 \ No newline at end of file diff --git a/src/test/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/SolutionTest.java b/src/test/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/SolutionTest.java new file mode 100644 index 000000000..5b5d9c90c --- /dev/null +++ b/src/test/java/g3501_3600/s3541_find_most_frequent_vowel_and_consonant/SolutionTest.java @@ -0,0 +1,18 @@ +package g3501_3600.s3541_find_most_frequent_vowel_and_consonant; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void maxFreqSum() { + assertThat(new Solution().maxFreqSum("successes"), equalTo(6)); + } + + @Test + void maxFreqSum2() { + assertThat(new Solution().maxFreqSum("aeiaeia"), equalTo(3)); + } +} diff --git a/src/test/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/SolutionTest.java b/src/test/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/SolutionTest.java new file mode 100644 index 000000000..39e0a95b2 --- /dev/null +++ b/src/test/java/g3501_3600/s3542_minimum_operations_to_convert_all_elements_to_zero/SolutionTest.java @@ -0,0 +1,23 @@ +package g3501_3600.s3542_minimum_operations_to_convert_all_elements_to_zero; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minOperations() { + assertThat(new Solution().minOperations(new int[] {0, 2}), equalTo(1)); + } + + @Test + void minOperations2() { + assertThat(new Solution().minOperations(new int[] {3, 1, 2, 1}), equalTo(3)); + } + + @Test + void minOperations3() { + assertThat(new Solution().minOperations(new int[] {1, 2, 1, 2, 1, 2}), equalTo(4)); + } +} diff --git a/src/test/java/g3501_3600/s3543_maximum_weighted_k_edge_path/SolutionTest.java b/src/test/java/g3501_3600/s3543_maximum_weighted_k_edge_path/SolutionTest.java new file mode 100644 index 000000000..dd84b2822 --- /dev/null +++ b/src/test/java/g3501_3600/s3543_maximum_weighted_k_edge_path/SolutionTest.java @@ -0,0 +1,63 @@ +package g3501_3600.s3543_maximum_weighted_k_edge_path; + +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(3, new int[][] {{0, 1, 1}, {1, 2, 2}}, 2, 4), equalTo(3)); + } + + @Test + void maxWeight2() { + assertThat( + new Solution().maxWeight(3, new int[][] {{0, 1, 2}, {0, 2, 3}}, 1, 3), equalTo(2)); + } + + @Test + void maxWeight3() { + assertThat( + new Solution().maxWeight(3, new int[][] {{0, 1, 6}, {1, 2, 8}}, 1, 6), equalTo(-1)); + } + + @Test + void maxWeight4() { + assertThat( + new Solution().maxWeight(3, new int[][] {{0, 1, 6}, {1, 2, 8}}, 0, 6), equalTo(0)); + } + + @Test + void maxWeight5() { + assertThat( + new Solution() + .maxWeight( + 6, + new int[][] { + {0, 1, 10}, + {0, 2, 1}, + {1, 3, 2}, + {2, 3, 5}, + {3, 4, 5}, + {3, 5, 3} + }, + 3, + 12), + equalTo(11)); + } + + @Test + void maxWeight6() { + assertThat( + new Solution() + .maxWeight( + 5, + new int[][] {{0, 1, 2}, {0, 2, 3}, {1, 3, 3}, {2, 3, 1}, {3, 4, 2}}, + 3, + 7), + equalTo(6)); + } +} diff --git a/src/test/java/g3501_3600/s3544_subtree_inversion_sum/SolutionTest.java b/src/test/java/g3501_3600/s3544_subtree_inversion_sum/SolutionTest.java new file mode 100644 index 000000000..cfaeb4ac4 --- /dev/null +++ b/src/test/java/g3501_3600/s3544_subtree_inversion_sum/SolutionTest.java @@ -0,0 +1,39 @@ +package g3501_3600.s3544_subtree_inversion_sum; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void subtreeInversionSum() { + assertThat( + new Solution() + .subtreeInversionSum( + new int[][] {{0, 1}, {0, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}}, + new int[] {4, -8, -6, 3, 7, -2, 5}, + 2), + equalTo(27L)); + } + + @Test + void subtreeInversionSum2() { + assertThat( + new Solution() + .subtreeInversionSum( + new int[][] {{0, 1}, {1, 2}, {2, 3}, {3, 4}}, + new int[] {-1, 3, -2, 4, -5}, + 2), + equalTo(9L)); + } + + @Test + void subtreeInversionSum3() { + assertThat( + new Solution() + .subtreeInversionSum( + new int[][] {{0, 1}, {0, 2}}, new int[] {0, -1, -2}, 3), + equalTo(3L)); + } +} diff --git a/src/test/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/SolutionTest.java b/src/test/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/SolutionTest.java new file mode 100644 index 000000000..05907e9c9 --- /dev/null +++ b/src/test/java/g3501_3600/s3545_minimum_deletions_for_at_most_k_distinct_characters/SolutionTest.java @@ -0,0 +1,23 @@ +package g3501_3600.s3545_minimum_deletions_for_at_most_k_distinct_characters; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minDeletion() { + assertThat(new Solution().minDeletion("abc", 2), equalTo(1)); + } + + @Test + void minDeletion2() { + assertThat(new Solution().minDeletion("aabb", 2), equalTo(0)); + } + + @Test + void minDeletion3() { + assertThat(new Solution().minDeletion("yyyzz", 1), equalTo(2)); + } +} diff --git a/src/test/java/g3501_3600/s3546_equal_sum_grid_partition_i/SolutionTest.java b/src/test/java/g3501_3600/s3546_equal_sum_grid_partition_i/SolutionTest.java new file mode 100644 index 000000000..cc67f8d97 --- /dev/null +++ b/src/test/java/g3501_3600/s3546_equal_sum_grid_partition_i/SolutionTest.java @@ -0,0 +1,23 @@ +package g3501_3600.s3546_equal_sum_grid_partition_i; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void canPartitionGrid() { + assertThat(new Solution().canPartitionGrid(new int[][] {{1, 4}, {2, 3}}), equalTo(true)); + } + + @Test + void canPartitionGrid2() { + assertThat(new Solution().canPartitionGrid(new int[][] {{1, 3}, {2, 4}}), equalTo(false)); + } + + @Test + void canPartitionGrid3() { + assertThat(new Solution().canPartitionGrid(new int[][] {{1}}), equalTo(false)); + } +} diff --git a/src/test/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/SolutionTest.java b/src/test/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/SolutionTest.java new file mode 100644 index 000000000..91020151d --- /dev/null +++ b/src/test/java/g3501_3600/s3547_maximum_sum_of_edge_values_in_a_graph/SolutionTest.java @@ -0,0 +1,24 @@ +package g3501_3600.s3547_maximum_sum_of_edge_values_in_a_graph; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void maxScore() { + assertThat( + new Solution() + .maxScore(7, new int[][] {{0, 1}, {1, 2}, {2, 0}, {3, 4}, {4, 5}, {5, 6}}), + equalTo(130L)); + } + + @Test + void maxScore2() { + assertThat( + new Solution() + .maxScore(6, new int[][] {{0, 3}, {4, 5}, {2, 0}, {1, 3}, {2, 4}, {1, 5}}), + equalTo(82L)); + } +} diff --git a/src/test/java/g3501_3600/s3548_equal_sum_grid_partition_ii/SolutionTest.java b/src/test/java/g3501_3600/s3548_equal_sum_grid_partition_ii/SolutionTest.java new file mode 100644 index 000000000..424d87bc8 --- /dev/null +++ b/src/test/java/g3501_3600/s3548_equal_sum_grid_partition_ii/SolutionTest.java @@ -0,0 +1,77 @@ +package g3501_3600.s3548_equal_sum_grid_partition_ii; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void canPartitionGrid() { + assertThat(new Solution().canPartitionGrid(new int[][] {{1, 4}, {2, 3}}), equalTo(true)); + } + + @Test + void canPartitionGrid2() { + assertThat(new Solution().canPartitionGrid(new int[][] {{1, 2}, {3, 4}}), equalTo(true)); + } + + @Test + void canPartitionGrid3() { + assertThat( + new Solution().canPartitionGrid(new int[][] {{1, 2, 4}, {2, 3, 5}}), + equalTo(false)); + } + + @Test + void canPartitionGrid4() { + assertThat( + new Solution().canPartitionGrid(new int[][] {{4, 1, 8}, {3, 2, 6}}), + equalTo(false)); + } + + @Test + void canPartitionGrid5() { + assertThat(new Solution().canPartitionGrid(new int[][] {{1}}), equalTo(false)); + } + + @Test + void canPartitionGrid6() { + assertThat( + new Solution().canPartitionGrid(new int[][] {{25372, 100000, 100000}}), + equalTo(true)); + } + + @Test + void canPartitionGrid7() { + assertThat( + new Solution().canPartitionGrid(new int[][] {{100000, 100000, 100000, 100000, 1}}), + equalTo(true)); + } + + @Test + void canPartitionGrid8() { + assertThat(new Solution().canPartitionGrid(new int[][] {{55753, 55753}}), equalTo(true)); + } + + @Test + void canPartitionGrid9() { + assertThat(new Solution().canPartitionGrid(new int[][] {{253, 10, 10}}), equalTo(true)); + } + + @Test + void canPartitionGrid10() { + assertThat( + new Solution().canPartitionGrid(new int[][] {{4, 4, 4}, {2, 2, 1}, {1, 1, 1}}), + equalTo(true)); + } + + @Test + void canPartitionGrid11() { + assertThat( + new Solution() + .canPartitionGrid( + new int[][] {{2, 40, 2}, {4, 2, 3}, {5, 1, 6}, {7, 8, 9}}), + equalTo(true)); + } +}