Given a m * n matrix seats that represent seats distributions in a classroom. If a seat is broken, it is denoted by '#' character otherwise it is denoted by a '.' character.
Students can see the answers of those sitting next to the left, right, upper left and upper right, but he cannot see the answers of the student sitting directly in front or behind him. Return the maximum number of students that can take the exam together without any cheating being possible.
Students must be placed in seats in good condition.
Example 1:
Input: seats = [["#",".","#","#",".","#"], [".","#","#","#","#","."], ["#",".","#","#",".","#"]] Output: 4 Explanation: Teacher can place 4 students in available seats so they don't cheat on the exam.
Example 2:
Input: seats = [[".","#"], ["#","#"], ["#","."], ["#","#"], [".","#"]] Output: 3 Explanation: Place all students in available seats.
Example 3:
Input: seats = [["#",".",".",".","#"], [".","#",".","#","."], [".",".","#",".","."], [".","#",".","#","."], ["#",".",".",".","#"]] Output: 10 Explanation: Place students in available seats in column 1, 3 and 5.
Constraints:
seats contains only characters '.' and'#'.m == seats.lengthn == seats[i].length1 <= m <= 81 <= n <= 8Problem Overview: You receive a classroom matrix where '.' represents a usable seat and '#' represents a broken one. Students cannot sit next to each other horizontally or diagonally across rows because they could cheat. The goal is to place the maximum number of students while respecting these constraints.
Approach 1: Backtracking with Pruning (Exponential Time, O(2^(m*n)) time, O(m*n) space)
This approach tries every valid seating configuration. You recursively decide whether to place a student in each seat while checking cheating constraints: no left/right neighbor in the same row and no upper-left or upper-right neighbor from the previous row. Pruning removes branches early when a placement violates rules. While straightforward, the state space grows quickly for larger grids, making it impractical for worst‑case inputs.
Approach 2: Bitmask Dynamic Programming (O(m * 2^n * 2^n) time, O(m * 2^n) space)
This optimized approach models each row as a bitmask representing which seats contain students. First generate all valid row masks where no two students sit adjacent horizontally and broken seats are excluded. Then use dynamic programming across rows: for each row mask, iterate over all valid masks from the previous row and ensure diagonal cheating rules are satisfied using bit operations like (mask << 1) and (mask >> 1). The DP state dp[row][mask] stores the maximum students up to that row with the given configuration. Bit operations make compatibility checks constant time, which drastically reduces the search space.
This technique combines bit manipulation with row‑by‑row DP over the matrix. Because each row has at most 2^n configurations (with n ≤ 8 in constraints), the algorithm remains tractable even for multiple rows.
Recommended for interviews: Bitmask Dynamic Programming is the expected solution. Interviewers want to see that you can compress row states with bitmasks and validate constraints using bit shifts. Backtracking demonstrates understanding of the constraints, but the DP approach shows stronger algorithmic optimization skills.
This approach uses dynamic programming with bitmasks to represent the state of each row. You iterate through each row while keeping track of all allowed seat arrangements, updating possible arrangements for the subsequent rows. The idea is to maximize the number of students placed while satisfying the constraints (no students adjacent).
The solution involves creating a dynamic programming array where every state represents a valid seating arrangement in a row using a bitmask. For each row, compute all valid seating patterns and transition states by checking if placing students in the current row conflicts with the previous one. Maximize the count of seated students.
Time complexity: O(m * 3^n), where m is the number of rows and n the number of columns because each row configuration can have up to 3^n states.
Space complexity: O(3^n), for storing the DP states.
In this approach, use backtracking with pruning to maximize the number of placed students. You attempt to place a student in each seat and check for conflicts recursively, pruning invalid configurations early. Although slower than DP, this method works due to the constraints on m and n.
The backtracking algorithm places a student at each position if possible. It checks left, right, upper-left, and upper-right neighbors to avoid cheating. If a valid position for a student is found, it records the result and continues. Using a recursive function, the solution explores valid configurations and prunes branches where cheating could occur.
Time complexity: O(2^(m*n)), as each position has two possibilities: occupied or not. However, pruning significantly reduces the actual search space.
Space complexity: O(m * n), which is the recursion call stack size.
We notice that each seat has two states: selectable and non-selectable. Therefore, we can use a binary number to represent the seat state of each row, where 1 represents selectable, and 0 represents non-selectable. For example, for the first row in Example 1, we can represent it as 010010. Therefore, we convert the initial seats into a one-dimensional array ss, where ss[i] represents the seat state of the ith row.
Next, we design a function dfs(seat, i), which represents the maximum number of students that can be accommodated starting from the ith row, and the seat state of the current row is seat.
We can enumerate all the seat selection states mask of the ith row, and judge whether mask meets the following conditions:
mask cannot select seats outside of seat;mask cannot select adjacent seats.If the conditions are met, we calculate the number of seats selected in the current row cnt. If it is the last row, update the return value of the function, that is, ans = max(ans, cnt). Otherwise, we continue to recursively solve the maximum number of the next row. The seat state of the next row is nxt = ss[i + 1], and we need to exclude the left and right sides of the selected seats in the current row. Then we recursively solve the maximum number of the next row, that is, ans = max(ans, cnt + dfs(nxt, i + 1)).
Finally, we return ans as the return value of the function.
To avoid repeated calculations, we can use memoization search to save the return value of the function dfs(seat, i) in a two-dimensional array f, where f[seat][i] represents the maximum number of students that can be accommodated starting from the ith row, and the seat state of the current row is seat.
The time complexity is O(4^n times n times m), and the space complexity is O(2^n times m). Where m and n are the number of rows and columns of the seats, respectively.
Python
Java
C++
Go
TypeScript
| Approach | Complexity |
|---|---|
| Bitmask Dynamic Programming | Time complexity: O(m * 3^n), where m is the number of rows and n the number of columns because each row configuration can have up to 3^n states. |
| Backtracking with Pruning | Time complexity: O(2^(m*n)), as each position has two possibilities: occupied or not. However, pruning significantly reduces the actual search space. |
| State Compression + Memoization Search | — |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Backtracking with Pruning | O(2^(m*n)) | O(m*n) | Good for understanding constraints or very small grids |
| Bitmask Dynamic Programming | O(m * 2^n * 2^n) | O(m * 2^n) | Optimal solution for interview settings and typical constraints |
LeetCode 1349. Maximum Students Taking Exam • Happy Coding • 3,343 views views
Watch 9 more video solutions →Practice Maximum Students Taking Exam with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor