From acb40f286b5a0a0b5f75aa5b7148f10152498be5 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Thu, 13 Mar 2025 03:46:07 +0200 Subject: [PATCH 1/3] Improved tasks 999, 1825, 3425 --- .../Solution.java | 124 +++++-------- .../s1825_finding_mk_average/MKAverage.java | 168 +++++------------- .../s3425_longest_special_path/Solution.java | 113 +++++------- 3 files changed, 132 insertions(+), 273 deletions(-) diff --git a/src/main/java/g0901_1000/s0999_available_captures_for_rook/Solution.java b/src/main/java/g0901_1000/s0999_available_captures_for_rook/Solution.java index e9b4f09f6..00c075b9f 100644 --- a/src/main/java/g0901_1000/s0999_available_captures_for_rook/Solution.java +++ b/src/main/java/g0901_1000/s0999_available_captures_for_rook/Solution.java @@ -1,97 +1,61 @@ package g0901_1000.s0999_available_captures_for_rook; -// #Easy #Array #Matrix #Simulation #2022_03_31_Time_0_ms_(100.00%)_Space_41.8_MB_(28.74%) +// #Easy #Array #Matrix #Simulation #2025_03_13_Time_0_ms_(100.00%)_Space_40.75_MB_(94.97%) @SuppressWarnings("java:S135") public class Solution { - private int[] directions = new int[] {0, 1, 0, -1, 0}; - public int numRookCaptures(char[][] board) { - int m = board.length; - int n = board[0].length; - int rowR = -1; - int colR = -1; - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { + // Find the position of the rook + int rookRow = -1; + int rookCol = -1; + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { if (board[i][j] == 'R') { - rowR = i; - colR = j; + rookRow = i; + rookCol = j; break; } } - } - int[] count = {0}; - for (int i = 0; i < 4; i++) { - int neighborRow = rowR + directions[i]; - int neighborCol = colR + directions[i + 1]; - if (neighborRow >= 0 - && neighborRow < m - && neighborCol >= 0 - && neighborCol < n - && board[neighborRow][neighborCol] != 'B') { - if (directions[i] == 0 && directions[i + 1] == 1) { - extracted(board, n, count, neighborRow, neighborCol); - } else if (directions[i] == 1 && directions[i + 1] == 0) { - extracted1(board, m, count, neighborRow, neighborCol); - } else if (directions[i] == 0 && directions[i + 1] == -1) { - extracted(board, count, neighborRow, neighborCol); - } else { - extracted1(board, count, neighborRow, neighborCol); - } - } - } - return count[0]; - } - - private void extracted(char[][] board, int[] count, int neighborRow, int neighborCol) { - while (neighborCol >= 0) { - if (board[neighborRow][neighborCol] == 'p') { - count[0]++; - break; - } else if (board[neighborRow][neighborCol] == 'B') { - break; - } else { - neighborCol--; - } - } - } - - private void extracted(char[][] board, int n, int[] count, int neighborRow, int neighborCol) { - while (neighborCol < n) { - if (board[neighborRow][neighborCol] == 'p') { - count[0]++; - break; - } else if (board[neighborRow][neighborCol] == 'B') { - break; - } else { - neighborCol++; - } - } - } - - private void extracted1(char[][] board, int[] count, int neighborRow, int neighborCol) { - while (neighborRow >= 0) { - if (board[neighborRow][neighborCol] == 'p') { - count[0]++; + if (rookRow != -1) { break; - } else if (board[neighborRow][neighborCol] == 'B') { - break; - } else { - neighborRow--; } } - } - - private void extracted1(char[][] board, int m, int[] count, int neighborRow, int neighborCol) { - while (neighborRow < m) { - if (board[neighborRow][neighborCol] == 'p') { - count[0]++; - break; - } else if (board[neighborRow][neighborCol] == 'B') { - break; - } else { - neighborRow++; + // Define the four directions: up, right, down, left + int[][] directions = { + // up + {-1, 0}, + // right + {0, 1}, + // down + {1, 0}, + // left + {0, -1} + }; + int captureCount = 0; + // Check each direction + for (int[] dir : directions) { + int row = rookRow; + int col = rookCol; + while (true) { + // Move one step in the current direction + row += dir[0]; + col += dir[1]; + // Check if out of bounds + if (row < 0 || row >= 8 || col < 0 || col >= 8) { + break; + } + // If we hit a bishop, we're blocked + if (board[row][col] == 'B') { + break; + } + // If we hit a pawn, we can capture it and then we're blocked + if (board[row][col] == 'p') { + captureCount++; + break; + } + // Otherwise (empty square), continue in the same direction } } + return captureCount; } } diff --git a/src/main/java/g1801_1900/s1825_finding_mk_average/MKAverage.java b/src/main/java/g1801_1900/s1825_finding_mk_average/MKAverage.java index 05b80f672..a5cecc665 100644 --- a/src/main/java/g1801_1900/s1825_finding_mk_average/MKAverage.java +++ b/src/main/java/g1801_1900/s1825_finding_mk_average/MKAverage.java @@ -1,141 +1,69 @@ package g1801_1900.s1825_finding_mk_average; // #Hard #Design #Heap_Priority_Queue #Ordered_Set #Queue -// #2022_05_06_Time_83_ms_(60.59%)_Space_96.3_MB_(77.83%) +// #2025_03_13_Time_37_ms_(100.00%)_Space_100.84_MB_(46.09%) -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.TreeMap; +import java.util.LinkedList; +import java.util.TreeSet; @SuppressWarnings("java:S2184") public class MKAverage { - private final double m; - private final double k; - private final double c; - private double avg; - private final Bst middle; - private final Bst min; - private final Bst max; - private final Deque q; + private int capacity; + private int boundary; + private int[] nums; + private TreeSet numSet; + private LinkedList order; public MKAverage(int m, int k) { - this.m = m; - this.k = k; - this.c = m - k * 2; - this.avg = 0; - this.middle = new Bst(); - this.min = new Bst(); - this.max = new Bst(); - this.q = new ArrayDeque<>(); + this.capacity = m; + this.boundary = k; + nums = new int[100001]; + numSet = new TreeSet<>(); + order = new LinkedList<>(); } public void addElement(int num) { - if (min.size < k) { - min.add(num); - q.offer(num); - return; - } - if (max.size < k) { - min.add(num); - max.add(min.removeMax()); - q.offer(num); - return; - } - - if (num >= min.lastKey() && num <= max.firstKey()) { - middle.add(num); - avg += num / c; - } else if (num < min.lastKey()) { - min.add(num); - int val = min.removeMax(); - middle.add(val); - avg += val / c; - } else if (num > max.firstKey()) { - max.add(num); - int val = max.removeMin(); - middle.add(val); - avg += val / c; - } - - q.offer(num); - - if (q.size() > m) { - num = q.poll(); - if (middle.containsKey(num)) { - avg -= num / c; - middle.remove(num); - } else if (min.containsKey(num)) { - min.remove(num); - int val = middle.removeMin(); - avg -= val / c; - min.add(val); - } else if (max.containsKey(num)) { - max.remove(num); - int val = middle.removeMax(); - avg -= val / c; - max.add(val); + if (order.size() == capacity) { + int numToDelete = order.removeFirst(); + nums[numToDelete] = nums[numToDelete] - 1; + if (nums[numToDelete] == 0) { + numSet.remove(numToDelete); } } + nums[num]++; + numSet.add(num); + order.add(num); } public int calculateMKAverage() { - if (q.size() < m) { - return -1; - } - return (int) avg; - } - - static class Bst { - TreeMap map; - int size; - - public Bst() { - this.map = new TreeMap<>(); - this.size = 0; - } - - void add(int num) { - int count = map.getOrDefault(num, 0) + 1; - map.put(num, count); - size++; - } - - void remove(int num) { - int count = map.getOrDefault(num, 1) - 1; - if (count > 0) { - map.put(num, count); - } else { - map.remove(num); + if (order.size() == capacity) { + int skipCount = boundary; + int numsCount = capacity - 2 * boundary; + int freq = capacity - 2 * boundary; + int sum = 0; + for (int num : numSet) { + int count = nums[num]; + if (skipCount < 0) { + sum += num * Math.min(count, numsCount); + numsCount -= Math.min(count, numsCount); + } else { + skipCount -= count; + if (skipCount < 0) { + sum += num * Math.min(Math.abs(skipCount), numsCount); + numsCount -= Math.min(Math.abs(skipCount), numsCount); + } + } + if (numsCount == 0) { + break; + } } - size--; - } - - int removeMin() { - int key = map.firstKey(); - - remove(key); - - return key; - } - - int removeMax() { - int key = map.lastKey(); - - remove(key); - - return key; - } - - boolean containsKey(int key) { - return map.containsKey(key); - } - - int firstKey() { - return map.firstKey(); - } - - int lastKey() { - return map.lastKey(); + return sum / freq; } + return -1; } } + +/** + * Your MKAverage object will be instantiated and called as such: MKAverage obj = new MKAverage(m, + * k); obj.addElement(num); int param_2 = obj.calculateMKAverage(); + */ diff --git a/src/main/java/g3401_3500/s3425_longest_special_path/Solution.java b/src/main/java/g3401_3500/s3425_longest_special_path/Solution.java index 2a225b1fd..0cb475611 100644 --- a/src/main/java/g3401_3500/s3425_longest_special_path/Solution.java +++ b/src/main/java/g3401_3500/s3425_longest_special_path/Solution.java @@ -1,96 +1,63 @@ package g3401_3500.s3425_longest_special_path; // #Hard #Array #Hash_Table #Depth_First_Search #Tree #Sliding_Window -// #2025_01_22_Time_49_ms_(74.66%)_Space_98.04_MB_(44.26%) +// #2025_03_13_Time_48_ms_(81.52%)_Space_86.51_MB_(86.87%) import java.util.ArrayList; -import java.util.Arrays; +import java.util.List; @SuppressWarnings("unchecked") public class Solution { - private ArrayList[] adj; - private int[] nums; - private int[] dist; - private int[] lastOccur; - private ArrayList pathStack; - private int minIndex; - private int maxLen; - private int minNodesForMaxLen; - public int[] longestSpecialPath(int[][] edges, int[] nums) { - int n = nums.length; - this.nums = nums; - adj = new ArrayList[n]; + int n = edges.length + 1; + int max = 0; + List[] adj = new List[n]; for (int i = 0; i < n; i++) { adj[i] = new ArrayList<>(); + max = Math.max(nums[i], max); } for (int[] e : edges) { - int u = e[0]; - int v = e[1]; - int w = e[2]; - adj[u].add(new int[] {v, w}); - adj[v].add(new int[] {u, w}); - } - dist = new int[n]; - buildDist(0, -1, 0); - int maxVal = 0; - for (int val : nums) { - if (val > maxVal) { - maxVal = val; - } + adj[e[0]].add(new int[] {e[1], e[2]}); + adj[e[1]].add(new int[] {e[0], e[2]}); } - lastOccur = new int[maxVal + 1]; - Arrays.fill(lastOccur, -1); - pathStack = new ArrayList<>(); - minIndex = 0; - maxLen = 0; - minNodesForMaxLen = Integer.MAX_VALUE; - dfs(0, -1); - return new int[] {maxLen, minNodesForMaxLen}; + int[] dist = new int[n]; + int[] res = new int[] {0, Integer.MAX_VALUE}; + int[] st = new int[n + 1]; + Integer[] seen = new Integer[max + 1]; + dfs(adj, nums, res, dist, seen, st, 0, -1, 0, 0); + return res; } - private void buildDist(int u, int parent, int currDist) { - dist[u] = currDist; - for (int[] edge : adj[u]) { - int v = edge[0]; - int w = edge[1]; - if (v == parent) { - continue; - } - buildDist(v, u, currDist + w); + private void dfs( + List[] adj, + int[] nums, + int[] res, + int[] dist, + Integer[] seen, + int[] st, + int node, + int parent, + int start, + int pos) { + Integer last = seen[nums[node]]; + if (last != null && last >= start) { + start = last + 1; } - } - - private void dfs(int u, int parent) { - int stackPos = pathStack.size(); - pathStack.add(u); - int val = nums[u]; - int oldPos = lastOccur[val]; - int oldMinIndex = minIndex; - lastOccur[val] = stackPos; - if (oldPos >= minIndex) { - minIndex = oldPos + 1; - } - if (minIndex <= stackPos) { - int ancestor = pathStack.get(minIndex); - int pathLength = dist[u] - dist[ancestor]; - int pathNodes = stackPos - minIndex + 1; - if (pathLength > maxLen) { - maxLen = pathLength; - minNodesForMaxLen = pathNodes; - } else if (pathLength == maxLen && pathNodes < minNodesForMaxLen) { - minNodesForMaxLen = pathNodes; - } + seen[nums[node]] = pos; + st[pos] = node; + int len = dist[node] - dist[st[start]]; + int sz = pos - start + 1; + if (res[0] < len || res[0] == len && res[1] > sz) { + res[0] = len; + res[1] = sz; } - for (int[] edge : adj[u]) { - int v = edge[0]; - if (v == parent) { + for (int[] neighbor : adj[node]) { + if (neighbor[0] == parent) { continue; } - dfs(v, u); + dist[neighbor[0]] = dist[node] + neighbor[1]; + dfs(adj, nums, res, dist, seen, st, neighbor[0], node, start, pos + 1); } - pathStack.remove(pathStack.size() - 1); - lastOccur[val] = oldPos; - minIndex = oldMinIndex; + seen[nums[node]] = last; } } From 3cf156e3e446a80811b7e5f2837d3834bd8f6c5b Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Thu, 13 Mar 2025 03:57:38 +0200 Subject: [PATCH 2/3] Fixed sonar --- .../s1825_finding_mk_average/MKAverage.java | 19 ++++++++++--------- .../s3425_longest_special_path/Solution.java | 2 +- .../MKAverageTest.java | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/main/java/g1801_1900/s1825_finding_mk_average/MKAverage.java b/src/main/java/g1801_1900/s1825_finding_mk_average/MKAverage.java index a5cecc665..a5404e32a 100644 --- a/src/main/java/g1801_1900/s1825_finding_mk_average/MKAverage.java +++ b/src/main/java/g1801_1900/s1825_finding_mk_average/MKAverage.java @@ -6,13 +6,12 @@ import java.util.LinkedList; import java.util.TreeSet; -@SuppressWarnings("java:S2184") public class MKAverage { - private int capacity; - private int boundary; - private int[] nums; - private TreeSet numSet; - private LinkedList order; + private final int capacity; + private final int boundary; + private final int[] nums; + private final TreeSet numSet; + private final LinkedList order; public MKAverage(int m, int k) { this.capacity = m; @@ -63,7 +62,9 @@ public int calculateMKAverage() { } } -/** - * Your MKAverage object will be instantiated and called as such: MKAverage obj = new MKAverage(m, - * k); obj.addElement(num); int param_2 = obj.calculateMKAverage(); +/* + * Your MKAverage object will be instantiated and called as such: + * MKAverage obj = new MKAverage(m, k); + * obj.addElement(num); + * int param_2 = obj.calculateMKAverage(); */ diff --git a/src/main/java/g3401_3500/s3425_longest_special_path/Solution.java b/src/main/java/g3401_3500/s3425_longest_special_path/Solution.java index 0cb475611..644040f39 100644 --- a/src/main/java/g3401_3500/s3425_longest_special_path/Solution.java +++ b/src/main/java/g3401_3500/s3425_longest_special_path/Solution.java @@ -6,7 +6,7 @@ import java.util.ArrayList; import java.util.List; -@SuppressWarnings("unchecked") +@SuppressWarnings({"java:S107", "unchecked"}) public class Solution { public int[] longestSpecialPath(int[][] edges, int[] nums) { int n = edges.length + 1; diff --git a/src/test/java/g1801_1900/s1825_finding_mk_average/MKAverageTest.java b/src/test/java/g1801_1900/s1825_finding_mk_average/MKAverageTest.java index 1ca69d8b5..a4eeebac2 100644 --- a/src/test/java/g1801_1900/s1825_finding_mk_average/MKAverageTest.java +++ b/src/test/java/g1801_1900/s1825_finding_mk_average/MKAverageTest.java @@ -19,4 +19,18 @@ void mKAverage() { obj.addElement(5); assertThat(obj.calculateMKAverage(), equalTo(5)); } + + @Test + void mKAverage2() { + MKAverage obj = new MKAverage(6, 1); + obj.addElement(3); + obj.addElement(1); + assertThat(obj.calculateMKAverage(), equalTo(-1)); + obj.addElement(12); + assertThat(obj.calculateMKAverage(), equalTo(-1)); + obj.addElement(5); + obj.addElement(3); + obj.addElement(4); + assertThat(obj.calculateMKAverage(), equalTo(3)); + } } From 95413435b65fda671b5a4ffc3cc214e4ee976027 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Thu, 13 Mar 2025 04:06:35 +0200 Subject: [PATCH 3/3] Added test --- .../SolutionTest.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/test/java/g0901_1000/s0999_available_captures_for_rook/SolutionTest.java b/src/test/java/g0901_1000/s0999_available_captures_for_rook/SolutionTest.java index 2163cadac..3e5939e45 100644 --- a/src/test/java/g0901_1000/s0999_available_captures_for_rook/SolutionTest.java +++ b/src/test/java/g0901_1000/s0999_available_captures_for_rook/SolutionTest.java @@ -59,4 +59,22 @@ void numRookCaptures3() { }), equalTo(3)); } + + @Test + void numRookCaptures4() { + assertThat( + new Solution() + .numRookCaptures( + new char[][] { + {'.', '.', '.', '.', '.', '.', '.', '.'}, + {'.', '.', '.', 'p', '.', '.', '.', '.'}, + {'.', '.', '.', 'R', '.', '.', '.', 'p'}, + {'.', '.', '.', '.', '.', '.', '.', '.'}, + {'.', '.', '.', '.', '.', '.', '.', '.'}, + {'.', '.', '.', 'p', '.', '.', '.', '.'}, + {'.', '.', '.', '.', '.', '.', '.', '.'}, + {'.', '.', '.', '.', '.', '.', '.', '.'} + }), + equalTo(3)); + } }