Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Move from brute-force thinking to an efficient approach using array strategy.
You are given an m x n grid classroom where a student volunteer is tasked with cleaning up litter scattered around the room. Each cell in the grid is one of the following:
'S': Starting position of the student'L': Litter that must be collected (once collected, the cell becomes empty)'R': Reset area that restores the student's energy to full capacity, regardless of their current energy level (can be used multiple times)'X': Obstacle the student cannot pass through'.': Empty spaceYou are also given an integer energy, representing the student's maximum energy capacity. The student starts with this energy from the starting position 'S'.
Each move to an adjacent cell (up, down, left, or right) costs 1 unit of energy. If the energy reaches 0, the student can only continue if they are on a reset area 'R', which resets the energy to its maximum capacity energy.
Return the minimum number of moves required to collect all litter items, or -1 if it's impossible.
Example 1:
Input: classroom = ["S.", "XL"], energy = 2
Output: 2
Explanation:
(0, 0) with 2 units of energy.(1, 0) contains an obstacle 'X', the student cannot move directly downward.(0, 0) → (0, 1) with 1 unit of energy and 1 unit remaining.(0, 1) → (1, 1) to collect the litter 'L'.Example 2:
Input: classroom = ["LS", "RL"], energy = 4
Output: 3
Explanation:
(0, 1) with 4 units of energy.(0, 1) → (0, 0) to collect the first litter 'L' with 1 unit of energy used and 3 units remaining.(0, 0) → (1, 0) to 'R' to reset and restore energy back to 4.(1, 0) → (1, 1) to collect the second litter 'L'.Example 3:
Input: classroom = ["L.S", "RXL"], energy = 3
Output: -1
Explanation:
No valid path collects all 'L'.
Constraints:
1 <= m == classroom.length <= 201 <= n == classroom[i].length <= 20classroom[i][j] is one of 'S', 'L', 'R', 'X', or '.'1 <= energy <= 50'S' in the grid.'L' cells in the grid.Problem summary: You are given an m x n grid classroom where a student volunteer is tasked with cleaning up litter scattered around the room. Each cell in the grid is one of the following: 'S': Starting position of the student 'L': Litter that must be collected (once collected, the cell becomes empty) 'R': Reset area that restores the student's energy to full capacity, regardless of their current energy level (can be used multiple times) 'X': Obstacle the student cannot pass through '.': Empty space You are also given an integer energy, representing the student's maximum energy capacity. The student starts with this energy from the starting position 'S'. Each move to an adjacent cell (up, down, left, or right) costs 1 unit of energy. If the energy reaches 0, the student can only continue if they are on a reset area 'R', which resets the energy to its maximum capacity energy. Return the minimum number of
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Hash Map · Bit Manipulation
["S.", "XL"] 2
["LS", "RL"] 4
["L.S", "RXL"] 3
Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3568: Minimum Moves to Clean the Classroom
class Solution {
public int minMoves(String[] classroom, int energy) {
int m = classroom.length, n = classroom[0].length();
int[][] d = new int[m][n];
int x = 0, y = 0, cnt = 0;
for (int i = 0; i < m; i++) {
String row = classroom[i];
for (int j = 0; j < n; j++) {
char c = row.charAt(j);
if (c == 'S') {
x = i;
y = j;
} else if (c == 'L') {
d[i][j] = cnt;
cnt++;
}
}
}
if (cnt == 0) {
return 0;
}
boolean[][][][] vis = new boolean[m][n][energy + 1][1 << cnt];
List<int[]> q = new ArrayList<>();
q.add(new int[] {x, y, energy, (1 << cnt) - 1});
vis[x][y][energy][(1 << cnt) - 1] = true;
int[] dirs = {-1, 0, 1, 0, -1};
int ans = 0;
while (!q.isEmpty()) {
List<int[]> t = q;
q = new ArrayList<>();
for (int[] state : t) {
int i = state[0], j = state[1], curEnergy = state[2], mask = state[3];
if (mask == 0) {
return ans;
}
if (curEnergy <= 0) {
continue;
}
for (int k = 0; k < 4; k++) {
int nx = i + dirs[k], ny = j + dirs[k + 1];
if (nx >= 0 && nx < m && ny >= 0 && ny < n && classroom[nx].charAt(ny) != 'X') {
int nxtEnergy = classroom[nx].charAt(ny) == 'R' ? energy : curEnergy - 1;
int nxtMask = mask;
if (classroom[nx].charAt(ny) == 'L') {
nxtMask &= ~(1 << d[nx][ny]);
}
if (!vis[nx][ny][nxtEnergy][nxtMask]) {
vis[nx][ny][nxtEnergy][nxtMask] = true;
q.add(new int[] {nx, ny, nxtEnergy, nxtMask});
}
}
}
}
ans++;
}
return -1;
}
}
// Accepted solution for LeetCode #3568: Minimum Moves to Clean the Classroom
func minMoves(classroom []string, energy int) int {
m, n := len(classroom), len(classroom[0])
d := make([][]int, m)
for i := range d {
d[i] = make([]int, n)
}
x, y, cnt := 0, 0, 0
for i := 0; i < m; i++ {
row := classroom[i]
for j := 0; j < n; j++ {
c := row[j]
if c == 'S' {
x, y = i, j
} else if c == 'L' {
d[i][j] = cnt
cnt++
}
}
}
if cnt == 0 {
return 0
}
vis := make([][][][]bool, m)
for i := range vis {
vis[i] = make([][][]bool, n)
for j := range vis[i] {
vis[i][j] = make([][]bool, energy+1)
for e := range vis[i][j] {
vis[i][j][e] = make([]bool, 1<<cnt)
}
}
}
type state struct {
i, j, curEnergy, mask int
}
q := []state{{x, y, energy, (1 << cnt) - 1}}
vis[x][y][energy][(1<<cnt)-1] = true
dirs := []int{-1, 0, 1, 0, -1}
ans := 0
for len(q) > 0 {
t := q
q = []state{}
for _, s := range t {
i, j, curEnergy, mask := s.i, s.j, s.curEnergy, s.mask
if mask == 0 {
return ans
}
if curEnergy <= 0 {
continue
}
for k := 0; k < 4; k++ {
nx, ny := i+dirs[k], j+dirs[k+1]
if nx >= 0 && nx < m && ny >= 0 && ny < n && classroom[nx][ny] != 'X' {
var nxtEnergy int
if classroom[nx][ny] == 'R' {
nxtEnergy = energy
} else {
nxtEnergy = curEnergy - 1
}
nxtMask := mask
if classroom[nx][ny] == 'L' {
nxtMask &= ^(1 << d[nx][ny])
}
if !vis[nx][ny][nxtEnergy][nxtMask] {
vis[nx][ny][nxtEnergy][nxtMask] = true
q = append(q, state{nx, ny, nxtEnergy, nxtMask})
}
}
}
}
ans++
}
return -1
}
# Accepted solution for LeetCode #3568: Minimum Moves to Clean the Classroom
class Solution:
def minMoves(self, classroom: List[str], energy: int) -> int:
m, n = len(classroom), len(classroom[0])
d = [[0] * n for _ in range(m)]
x = y = cnt = 0
for i, row in enumerate(classroom):
for j, c in enumerate(row):
if c == "S":
x, y = i, j
elif c == "L":
d[i][j] = cnt
cnt += 1
if cnt == 0:
return 0
vis = [
[[[False] * (1 << cnt) for _ in range(energy + 1)] for _ in range(n)]
for _ in range(m)
]
q = [(x, y, energy, (1 << cnt) - 1)]
vis[x][y][energy][(1 << cnt) - 1] = True
dirs = (-1, 0, 1, 0, -1)
ans = 0
while q:
t = q
q = []
for i, j, cur_energy, mask in t:
if mask == 0:
return ans
if cur_energy <= 0:
continue
for k in range(4):
x, y = i + dirs[k], j + dirs[k + 1]
if 0 <= x < m and 0 <= y < n and classroom[x][y] != "X":
nxt_energy = (
energy if classroom[x][y] == "R" else cur_energy - 1
)
nxt_mask = mask
if classroom[x][y] == "L":
nxt_mask &= ~(1 << d[x][y])
if not vis[x][y][nxt_energy][nxt_mask]:
vis[x][y][nxt_energy][nxt_mask] = True
q.append((x, y, nxt_energy, nxt_mask))
ans += 1
return -1
// Accepted solution for LeetCode #3568: Minimum Moves to Clean the Classroom
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3568: Minimum Moves to Clean the Classroom
// class Solution {
// public int minMoves(String[] classroom, int energy) {
// int m = classroom.length, n = classroom[0].length();
// int[][] d = new int[m][n];
// int x = 0, y = 0, cnt = 0;
// for (int i = 0; i < m; i++) {
// String row = classroom[i];
// for (int j = 0; j < n; j++) {
// char c = row.charAt(j);
// if (c == 'S') {
// x = i;
// y = j;
// } else if (c == 'L') {
// d[i][j] = cnt;
// cnt++;
// }
// }
// }
// if (cnt == 0) {
// return 0;
// }
// boolean[][][][] vis = new boolean[m][n][energy + 1][1 << cnt];
// List<int[]> q = new ArrayList<>();
// q.add(new int[] {x, y, energy, (1 << cnt) - 1});
// vis[x][y][energy][(1 << cnt) - 1] = true;
// int[] dirs = {-1, 0, 1, 0, -1};
// int ans = 0;
// while (!q.isEmpty()) {
// List<int[]> t = q;
// q = new ArrayList<>();
// for (int[] state : t) {
// int i = state[0], j = state[1], curEnergy = state[2], mask = state[3];
// if (mask == 0) {
// return ans;
// }
// if (curEnergy <= 0) {
// continue;
// }
// for (int k = 0; k < 4; k++) {
// int nx = i + dirs[k], ny = j + dirs[k + 1];
// if (nx >= 0 && nx < m && ny >= 0 && ny < n && classroom[nx].charAt(ny) != 'X') {
// int nxtEnergy = classroom[nx].charAt(ny) == 'R' ? energy : curEnergy - 1;
// int nxtMask = mask;
// if (classroom[nx].charAt(ny) == 'L') {
// nxtMask &= ~(1 << d[nx][ny]);
// }
// if (!vis[nx][ny][nxtEnergy][nxtMask]) {
// vis[nx][ny][nxtEnergy][nxtMask] = true;
// q.add(new int[] {nx, ny, nxtEnergy, nxtMask});
// }
// }
// }
// }
// ans++;
// }
// return -1;
// }
// }
// Accepted solution for LeetCode #3568: Minimum Moves to Clean the Classroom
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #3568: Minimum Moves to Clean the Classroom
// class Solution {
// public int minMoves(String[] classroom, int energy) {
// int m = classroom.length, n = classroom[0].length();
// int[][] d = new int[m][n];
// int x = 0, y = 0, cnt = 0;
// for (int i = 0; i < m; i++) {
// String row = classroom[i];
// for (int j = 0; j < n; j++) {
// char c = row.charAt(j);
// if (c == 'S') {
// x = i;
// y = j;
// } else if (c == 'L') {
// d[i][j] = cnt;
// cnt++;
// }
// }
// }
// if (cnt == 0) {
// return 0;
// }
// boolean[][][][] vis = new boolean[m][n][energy + 1][1 << cnt];
// List<int[]> q = new ArrayList<>();
// q.add(new int[] {x, y, energy, (1 << cnt) - 1});
// vis[x][y][energy][(1 << cnt) - 1] = true;
// int[] dirs = {-1, 0, 1, 0, -1};
// int ans = 0;
// while (!q.isEmpty()) {
// List<int[]> t = q;
// q = new ArrayList<>();
// for (int[] state : t) {
// int i = state[0], j = state[1], curEnergy = state[2], mask = state[3];
// if (mask == 0) {
// return ans;
// }
// if (curEnergy <= 0) {
// continue;
// }
// for (int k = 0; k < 4; k++) {
// int nx = i + dirs[k], ny = j + dirs[k + 1];
// if (nx >= 0 && nx < m && ny >= 0 && ny < n && classroom[nx].charAt(ny) != 'X') {
// int nxtEnergy = classroom[nx].charAt(ny) == 'R' ? energy : curEnergy - 1;
// int nxtMask = mask;
// if (classroom[nx].charAt(ny) == 'L') {
// nxtMask &= ~(1 << d[nx][ny]);
// }
// if (!vis[nx][ny][nxtEnergy][nxtMask]) {
// vis[nx][ny][nxtEnergy][nxtMask] = true;
// q.add(new int[] {nx, ny, nxtEnergy, nxtMask});
// }
// }
// }
// }
// ans++;
// }
// return -1;
// }
// }
Use this to step through a reusable interview workflow for this problem.
Sort the array in O(n log n), then scan for the missing or unique element by comparing adjacent pairs. Sorting requires O(n) auxiliary space (or O(1) with in-place sort but O(n log n) time remains). The sort step dominates.
Bitwise operations (AND, OR, XOR, shifts) are O(1) per operation on fixed-width integers. A single pass through the input with bit operations gives O(n) time. The key insight: XOR of a number with itself is 0, which eliminates duplicates without extra space.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.