diff --git a/src/main/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/Solution.java b/src/main/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/Solution.java new file mode 100644 index 000000000..7863b5ae1 --- /dev/null +++ b/src/main/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/Solution.java @@ -0,0 +1,37 @@ +package g3401_3500.s3417_zigzag_grid_traversal_with_skip; + +// #Easy #Array #Matrix #Simulation #2025_01_15_Time_1_(100.00%)_Space_45.56_(84.25%) + +import java.util.ArrayList; +import java.util.List; + +public class Solution { + public List zigzagTraversal(int[][] grid) { + List ans = new ArrayList<>(); + int m = grid.length; + int n = grid[0].length; + int i = 0; + boolean flag = true; + boolean skip = false; + while (i < m) { + if (flag) { + for (int j = 0; j < n; j++) { + if (!skip) { + ans.add(grid[i][j]); + } + skip = !skip; + } + } else { + for (int j = n - 1; j >= 0; j--) { + if (!skip) { + ans.add(grid[i][j]); + } + skip = !skip; + } + } + flag = !flag; + i++; + } + return ans; + } +} diff --git a/src/main/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/readme.md b/src/main/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/readme.md new file mode 100644 index 000000000..a652ca4a8 --- /dev/null +++ b/src/main/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/readme.md @@ -0,0 +1,54 @@ +3417\. Zigzag Grid Traversal With Skip + +Easy + +You are given an `m x n` 2D array `grid` of **positive** integers. + +Your task is to traverse `grid` in a **zigzag** pattern while skipping every **alternate** cell. + +Zigzag pattern traversal is defined as following the below actions: + +* Start at the top-left cell `(0, 0)`. +* Move _right_ within a row until the end of the row is reached. +* Drop down to the next row, then traverse _left_ until the beginning of the row is reached. +* Continue **alternating** between right and left traversal until every row has been traversed. + +**Note** that you **must skip** every _alternate_ cell during the traversal. + +Return an array of integers `result` containing, **in order**, the value of the cells visited during the zigzag traversal with skips. + +**Example 1:** + +**Input:** grid = [[1,2],[3,4]] + +**Output:** [1,4] + +**Explanation:** + +**![](https://assets.leetcode.com/uploads/2024/11/23/4012_example0.png)** + +**Example 2:** + +**Input:** grid = [[2,1],[2,1],[2,1]] + +**Output:** [2,1,2] + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2024/11/23/4012_example1.png) + +**Example 3:** + +**Input:** grid = [[1,2,3],[4,5,6],[7,8,9]] + +**Output:** [1,3,5,7,9] + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2024/11/23/4012_example2.png) + +**Constraints:** + +* `2 <= n == grid.length <= 50` +* `2 <= m == grid[i].length <= 50` +* `1 <= grid[i][j] <= 2500` \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/Solution.java b/src/main/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/Solution.java new file mode 100644 index 000000000..a91076041 --- /dev/null +++ b/src/main/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/Solution.java @@ -0,0 +1,56 @@ +package g3401_3500.s3418_maximum_amount_of_money_robot_can_earn; + +// #Medium #Array #Dynamic_Programming #Matrix #2025_01_15_Time_12_(99.86%)_Space_72.43_(98.47%) + +public class Solution { + public int maximumAmount(int[][] coins) { + int m = coins.length; + int n = coins[0].length; + int[][] dp = new int[m][n]; + int[][] dp1 = new int[m][n]; + int[][] dp2 = new int[m][n]; + dp[0][0] = coins[0][0]; + for (int j = 1; j < n; j++) { + dp[0][j] = dp[0][j - 1] + coins[0][j]; + } + for (int i = 1; i < m; i++) { + dp[i][0] = dp[i - 1][0] + coins[i][0]; + } + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]) + coins[i][j]; + } + } + dp1[0][0] = Math.max(coins[0][0], 0); + for (int j = 1; j < n; j++) { + dp1[0][j] = Math.max(dp[0][j - 1], dp1[0][j - 1] + coins[0][j]); + } + for (int i = 1; i < m; i++) { + dp1[i][0] = Math.max(dp[i - 1][0], dp1[i - 1][0] + coins[i][0]); + } + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + dp1[i][j] = + Math.max( + Math.max(dp[i][j - 1], dp[i - 1][j]), + Math.max(dp1[i][j - 1], dp1[i - 1][j]) + coins[i][j]); + } + } + dp2[0][0] = Math.max(coins[0][0], 0); + for (int j = 1; j < n; j++) { + dp2[0][j] = Math.max(dp1[0][j - 1], dp2[0][j - 1] + coins[0][j]); + } + for (int i = 1; i < m; i++) { + dp2[i][0] = Math.max(dp1[i - 1][0], dp2[i - 1][0] + coins[i][0]); + } + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + dp2[i][j] = + Math.max( + Math.max(dp1[i][j - 1], dp1[i - 1][j]), + Math.max(dp2[i][j - 1], dp2[i - 1][j]) + coins[i][j]); + } + } + return dp2[m - 1][n - 1]; + } +} diff --git a/src/main/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/readme.md b/src/main/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/readme.md new file mode 100644 index 000000000..40f1fa1a0 --- /dev/null +++ b/src/main/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/readme.md @@ -0,0 +1,54 @@ +3418\. Maximum Amount of Money Robot Can Earn + +Medium + +You are given an `m x n` grid. A robot starts at the top-left corner of the grid `(0, 0)` and wants to reach the bottom-right corner `(m - 1, n - 1)`. The robot can move either right or down at any point in time. + +The grid contains a value `coins[i][j]` in each cell: + +* If `coins[i][j] >= 0`, the robot gains that many coins. +* If `coins[i][j] < 0`, the robot encounters a robber, and the robber steals the **absolute** value of `coins[i][j]` coins. + +The robot has a special ability to **neutralize robbers** in at most **2 cells** on its path, preventing them from stealing coins in those cells. + +**Note:** The robot's total coins can be negative. + +Return the **maximum** profit the robot can gain on the route. + +**Example 1:** + +**Input:** coins = [[0,1,-1],[1,-2,3],[2,-3,4]] + +**Output:** 8 + +**Explanation:** + +An optimal path for maximum coins is: + +1. Start at `(0, 0)` with `0` coins (total coins = `0`). +2. Move to `(0, 1)`, gaining `1` coin (total coins = `0 + 1 = 1`). +3. Move to `(1, 1)`, where there's a robber stealing `2` coins. The robot uses one neutralization here, avoiding the robbery (total coins = `1`). +4. Move to `(1, 2)`, gaining `3` coins (total coins = `1 + 3 = 4`). +5. Move to `(2, 2)`, gaining `4` coins (total coins = `4 + 4 = 8`). + +**Example 2:** + +**Input:** coins = [[10,10,10],[10,10,10]] + +**Output:** 40 + +**Explanation:** + +An optimal path for maximum coins is: + +1. Start at `(0, 0)` with `10` coins (total coins = `10`). +2. Move to `(0, 1)`, gaining `10` coins (total coins = `10 + 10 = 20`). +3. Move to `(0, 2)`, gaining another `10` coins (total coins = `20 + 10 = 30`). +4. Move to `(1, 2)`, gaining the final `10` coins (total coins = `30 + 10 = 40`). + +**Constraints:** + +* `m == coins.length` +* `n == coins[i].length` +* `1 <= m, n <= 500` +* `-1000 <= coins[i][j] <= 1000` \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/Solution.java b/src/main/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/Solution.java new file mode 100644 index 000000000..12669cec0 --- /dev/null +++ b/src/main/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/Solution.java @@ -0,0 +1,84 @@ +package g3401_3500.s3419_minimize_the_maximum_edge_weight_of_graph; + +// #Medium #Binary_Search #Graph #Shortest_Path #Depth_First_Search #Breadth_First_Search +// #2025_01_15_Time_64_(99.28%)_Space_110.17_(57.63%) + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.Queue; + +@SuppressWarnings({"unchecked", "unused", "java:S1172"}) +public class Solution { + private ArrayList> revadj; + + private static class Pair { + int node; + int weight; + + public Pair(int node, int weight) { + this.node = node; + this.weight = weight; + } + } + + public int minMaxWeight(int n, int[][] edges, int threshold) { + ArrayList> adj = new ArrayList<>(); + revadj = new ArrayList<>(); + for (int i = 0; i <= n + 1; i++) { + adj.add(new ArrayList<>()); + revadj.add(new ArrayList<>()); + } + for (int[] edge : edges) { + int u = edge[0]; + int v = edge[1]; + int wt = edge[2]; + adj.get(u).add(new Pair(v, wt)); + revadj.get(v).add(new Pair(u, wt)); + } + if (!check(n)) { + return -1; + } + int[] dist = new int[n + 1]; + Arrays.fill(dist, (int) (1e9)); + dist[0] = 0; + Queue q = new LinkedList<>(); + q.offer(new Pair(0, 0)); + while (!q.isEmpty()) { + int u = q.peek().node; + int currMax = q.peek().weight; + q.poll(); + for (int i = 0; i < revadj.get(u).size(); i++) { + int v = revadj.get(u).get(i).node; + int wt = revadj.get(u).get(i).weight; + if (dist[v] > Math.max(wt, currMax)) { + dist[v] = Math.max(wt, currMax); + q.offer(new Pair(v, dist[v])); + } + } + } + int maxi = dist[0]; + for (int i = 0; i < n; i++) { + maxi = Math.max(maxi, dist[i]); + } + return maxi; + } + + private boolean check(int n) { + int[] vis = new int[n]; + ArrayList nodes = new ArrayList<>(); + dfs(0, vis, nodes); + return nodes.size() == n; + } + + private void dfs(int u, int[] vis, ArrayList nodes) { + nodes.add(u); + vis[u] = 1; + for (int i = 0; i < revadj.get(u).size(); i++) { + int v = revadj.get(u).get(i).node; + if (vis[v] == 0) { + dfs(v, vis, nodes); + } + } + } +} diff --git a/src/main/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/readme.md b/src/main/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/readme.md new file mode 100644 index 000000000..90c5eba33 --- /dev/null +++ b/src/main/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/readme.md @@ -0,0 +1,64 @@ +3419\. Minimize the Maximum Edge Weight of Graph + +Medium + +You are given two integers, `n` and `threshold`, as well as a **directed** weighted graph of `n` nodes numbered from 0 to `n - 1`. The graph is represented by a **2D** integer array `edges`, where edges[i] = [Ai, Bi, Wi] indicates that there is an edge going from node Ai to node Bi with weight Wi. + +You have to remove some edges from this graph (possibly **none**), so that it satisfies the following conditions: + +* Node 0 must be reachable from all other nodes. +* The **maximum** edge weight in the resulting graph is **minimized**. +* Each node has **at most** `threshold` outgoing edges. + +Return the **minimum** possible value of the **maximum** edge weight after removing the necessary edges. If it is impossible for all conditions to be satisfied, return -1. + +**Example 1:** + +**Input:** n = 5, edges = [[1,0,1],[2,0,2],[3,0,1],[4,3,1],[2,1,1]], threshold = 2 + +**Output:** 1 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2024/12/09/s-1.png) + +Remove the edge `2 -> 0`. The maximum weight among the remaining edges is 1. + +**Example 2:** + +**Input:** n = 5, edges = [[0,1,1],[0,2,2],[0,3,1],[0,4,1],[1,2,1],[1,4,1]], threshold = 1 + +**Output:** \-1 + +**Explanation:** + +It is impossible to reach node 0 from node 2. + +**Example 3:** + +**Input:** n = 5, edges = [[1,2,1],[1,3,3],[1,4,5],[2,3,2],[3,4,2],[4,0,1]], threshold = 1 + +**Output:** 2 + +**Explanation:** + +![](https://assets.leetcode.com/uploads/2024/12/09/s2-1.png) + +Remove the edges `1 -> 3` and `1 -> 4`. The maximum weight among the remaining edges is 2. + +**Example 4:** + +**Input:** n = 5, edges = [[1,2,1],[1,3,3],[1,4,5],[2,3,2],[4,0,1]], threshold = 1 + +**Output:** \-1 + +**Constraints:** + +* 2 <= n <= 105 +* `1 <= threshold <= n - 1` +* 1 <= edges.length <= min(105, n * (n - 1) / 2). +* `edges[i].length == 3` +* 0 <= Ai, Bi < n +* Ai != Bi +* 1 <= Wi <= 106 +* There **may be** multiple edges between a pair of nodes, but they must have unique weights. \ No newline at end of file diff --git a/src/main/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/Solution.java b/src/main/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/Solution.java new file mode 100644 index 000000000..28780ea83 --- /dev/null +++ b/src/main/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/Solution.java @@ -0,0 +1,38 @@ +package g3401_3500.s3420_count_non_decreasing_subarrays_after_k_operations; + +// #Hard #Array #Two_Pointers #Stack #Monotonic_Stack #Queue #Segment_Tree #Monotonic_Queue +// #2025_01_15_Time_29_(83.94%)_Space_62.04_(56.93%) + +import java.util.ArrayDeque; +import java.util.Deque; + +public class Solution { + public long countNonDecreasingSubarrays(int[] nums, long k) { + int n = nums.length; + for (int i = 0; i < n / 2; ++i) { + int temp = nums[i]; + nums[i] = nums[n - 1 - i]; + nums[n - 1 - i] = temp; + } + long res = 0; + Deque q = new ArrayDeque<>(); + int i = 0; + for (int j = 0; j < nums.length; ++j) { + while (!q.isEmpty() && nums[q.peekLast()] < nums[j]) { + int r = q.pollLast(); + int l = q.isEmpty() ? i - 1 : q.peekLast(); + k -= (long) (r - l) * (nums[j] - nums[r]); + } + q.addLast(j); + while (k < 0) { + k += nums[q.peekFirst()] - nums[i]; + if (q.peekFirst() == i) { + q.pollFirst(); + } + ++i; + } + res += j - i + 1; + } + return res; + } +} diff --git a/src/main/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/readme.md b/src/main/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/readme.md new file mode 100644 index 000000000..46169b39e --- /dev/null +++ b/src/main/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/readme.md @@ -0,0 +1,39 @@ +3420\. Count Non-Decreasing Subarrays After K Operations + +Hard + +You are given an array `nums` of `n` integers and an integer `k`. + +For each subarray of `nums`, you can apply **up to** `k` operations on it. In each operation, you increment any element of the subarray by 1. + +**Note** that each subarray is considered independently, meaning changes made to one subarray do not persist to another. + +Return the number of subarrays that you can make **non-decreasing** after performing at most `k` operations. + +An array is said to be **non-decreasing** if each element is greater than or equal to its previous element, if it exists. + +**Example 1:** + +**Input:** nums = [6,3,1,2,4,4], k = 7 + +**Output:** 17 + +**Explanation:** + +Out of all 21 possible subarrays of `nums`, only the subarrays `[6, 3, 1]`, `[6, 3, 1, 2]`, `[6, 3, 1, 2, 4]` and `[6, 3, 1, 2, 4, 4]` cannot be made non-decreasing after applying up to k = 7 operations. Thus, the number of non-decreasing subarrays is `21 - 4 = 17`. + +**Example 2:** + +**Input:** nums = [6,3,1,3,6], k = 4 + +**Output:** 12 + +**Explanation:** + +The subarray `[3, 1, 3, 6]` along with all subarrays of `nums` with three or fewer elements, except `[6, 3, 1]`, can be made non-decreasing after `k` operations. There are 5 subarrays of a single element, 4 subarrays of two elements, and 2 subarrays of three elements except `[6, 3, 1]`, so there are `1 + 5 + 4 + 2 = 12` subarrays that can be made non-decreasing. + +**Constraints:** + +* 1 <= nums.length <= 105 +* 1 <= nums[i] <= 109 +* 1 <= k <= 109 \ No newline at end of file diff --git a/src/test/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/SolutionTest.java b/src/test/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/SolutionTest.java new file mode 100644 index 000000000..ecd183508 --- /dev/null +++ b/src/test/java/g3401_3500/s3417_zigzag_grid_traversal_with_skip/SolutionTest.java @@ -0,0 +1,30 @@ +package g3401_3500.s3417_zigzag_grid_traversal_with_skip; + +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 zigzagTraversal() { + assertThat( + new Solution().zigzagTraversal(new int[][] {{1, 2}, {3, 4}}), + equalTo(List.of(1, 4))); + } + + @Test + void zigzagTraversal2() { + assertThat( + new Solution().zigzagTraversal(new int[][] {{2, 1}, {2, 1}, {2, 1}}), + equalTo(List.of(2, 1, 2))); + } + + @Test + void zigzagTraversal3() { + assertThat( + new Solution().zigzagTraversal(new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}), + equalTo(List.of(1, 3, 5, 7, 9))); + } +} diff --git a/src/test/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/SolutionTest.java b/src/test/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/SolutionTest.java new file mode 100644 index 000000000..d8af0f9d0 --- /dev/null +++ b/src/test/java/g3401_3500/s3418_maximum_amount_of_money_robot_can_earn/SolutionTest.java @@ -0,0 +1,22 @@ +package g3401_3500.s3418_maximum_amount_of_money_robot_can_earn; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void maximumAmount() { + assertThat( + new Solution().maximumAmount(new int[][] {{0, 1, -1}, {1, -2, 3}, {2, -3, 4}}), + equalTo(8)); + } + + @Test + void maximumAmount2() { + assertThat( + new Solution().maximumAmount(new int[][] {{10, 10, 10}, {10, 10, 10}}), + equalTo(40)); + } +} diff --git a/src/test/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/SolutionTest.java b/src/test/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/SolutionTest.java new file mode 100644 index 000000000..8ee38965a --- /dev/null +++ b/src/test/java/g3401_3500/s3419_minimize_the_maximum_edge_weight_of_graph/SolutionTest.java @@ -0,0 +1,56 @@ +package g3401_3500.s3419_minimize_the_maximum_edge_weight_of_graph; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void minMaxWeight() { + assertThat( + new Solution() + .minMaxWeight( + 5, + new int[][] {{1, 0, 1}, {2, 0, 2}, {3, 0, 1}, {4, 3, 1}, {2, 1, 1}}, + 2), + equalTo(1)); + } + + @Test + void minMaxWeight2() { + assertThat( + new Solution() + .minMaxWeight( + 5, + new int[][] { + {0, 1, 1}, {0, 2, 2}, {0, 3, 1}, {0, 4, 1}, {1, 2, 1}, {1, 4, 1} + }, + 1), + equalTo(-1)); + } + + @Test + void minMaxWeight3() { + assertThat( + new Solution() + .minMaxWeight( + 5, + new int[][] { + {1, 2, 1}, {1, 3, 3}, {1, 4, 5}, {2, 3, 2}, {3, 4, 2}, {4, 0, 1} + }, + 1), + equalTo(2)); + } + + @Test + void minMaxWeight4() { + assertThat( + new Solution() + .minMaxWeight( + 5, + new int[][] {{1, 2, 1}, {1, 3, 3}, {1, 4, 5}, {2, 3, 2}, {4, 0, 1}}, + 1), + equalTo(-1)); + } +} diff --git a/src/test/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/SolutionTest.java b/src/test/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/SolutionTest.java new file mode 100644 index 000000000..5a71b177f --- /dev/null +++ b/src/test/java/g3401_3500/s3420_count_non_decreasing_subarrays_after_k_operations/SolutionTest.java @@ -0,0 +1,22 @@ +package g3401_3500.s3420_count_non_decreasing_subarrays_after_k_operations; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +class SolutionTest { + @Test + void countNonDecreasingSubarrays() { + assertThat( + new Solution().countNonDecreasingSubarrays(new int[] {6, 3, 1, 2, 4, 4}, 7), + equalTo(17L)); + } + + @Test + void countNonDecreasingSubarrays2() { + assertThat( + new Solution().countNonDecreasingSubarrays(new int[] {6, 3, 1, 3, 6}, 4), + equalTo(12L)); + } +}