LeetCode 题解工作台
参加考试的最大学生数
给你一个 m * n 的矩阵 seats 表示教室中的座位分布。如果座位是坏的(不可用),就用 '#' 表示;否则,用 '.' 表示。 学生可以看到左侧、右侧、左上、右上这四个方向上紧邻他的学生的答卷,但是看不到直接坐在他前面或者后面的学生的答卷。请你计算并返回该考场可以容纳的同时参加考试且无法作弊…
5
题型
5
代码语言
3
相关题
当前训练重点
困难 · 状态·转移·动态规划
答案摘要
我们注意到,每个座位有两种状态:可选和不可选。因此,我们可以使用二进制数来表示每一行的座位状态,其中 表示可选,而 表示不可选。例如,对于示例 中的第一行,我们可以表示为 。因此,我们将初始座位转换为一个一维数组 ,其中 表示第 行的座位状态。 接下来,我们设计一个函数 $dfs(seat, i)$,表示从第 行开始,当前行的座位状态为 ,可以容纳的最多学生人数。
Interview AiBoxInterview AiBox 实时 AI 助手,陪你讲清 状态·转移·动态规划 题型思路
题目描述
给你一个 m * n 的矩阵 seats 表示教室中的座位分布。如果座位是坏的(不可用),就用 '#' 表示;否则,用 '.' 表示。
学生可以看到左侧、右侧、左上、右上这四个方向上紧邻他的学生的答卷,但是看不到直接坐在他前面或者后面的学生的答卷。请你计算并返回该考场可以容纳的同时参加考试且无法作弊的 最大 学生人数。
学生必须坐在状况良好的座位上。
示例 1:

输入:seats = [["#",".","#","#",".","#"], [".","#","#","#","#","."], ["#",".","#","#",".","#"]] 输出:4 解释:教师可以让 4 个学生坐在可用的座位上,这样他们就无法在考试中作弊。
示例 2:
输入:seats = [[".","#"], ["#","#"], ["#","."], ["#","#"], [".","#"]] 输出:3 解释:让所有学生坐在可用的座位上。
示例 3:
输入:seats = [["#",".",".",".","#"], [".","#",".","#","."], [".",".","#",".","."], [".","#",".","#","."], ["#",".",".",".","#"]] 输出:10 解释:让学生坐在第 1、3 和 5 列的可用座位上。
提示:
seats只包含字符'.' 和'#'m == seats.lengthn == seats[i].length1 <= m <= 81 <= n <= 8
解题思路
方法一:状态压缩 + 记忆化搜索
我们注意到,每个座位有两种状态:可选和不可选。因此,我们可以使用二进制数来表示每一行的座位状态,其中 表示可选,而 表示不可选。例如,对于示例 中的第一行,我们可以表示为 。因此,我们将初始座位转换为一个一维数组 ,其中 表示第 行的座位状态。
接下来,我们设计一个函数 ,表示从第 行开始,当前行的座位状态为 ,可以容纳的最多学生人数。
我们可以枚举第 行的所有选座状态 ,并且判断 是否满足以下条件:
- 状态 不能选择 之外的座位;
- 状态 不能选择相邻的座位。
如果满足条件,我们求出当前行选择的座位个数 ,如果当前是最后一行,则更新函数的返回值,即 。否则,我们继续递归地求解下一行的最大人数,下一行的座位状态 ,并且需要排除当前行已选座位的左右两侧。然后我们递归地求解下一行的最大人数,即 。
最后,我们将 作为函数的返回值返回。
为了避免重复计算,我们可以使用记忆化搜索,将函数 的返回值保存在一个二维数组 中,其中 表示从第 行开始,当前行的座位状态为 ,可以容纳的最多学生人数。
时间复杂度 ,空间复杂度 。其中 和 分别为座位的行数和列数。
class Solution:
def maxStudents(self, seats: List[List[str]]) -> int:
def f(seat: List[str]) -> int:
mask = 0
for i, c in enumerate(seat):
if c == '.':
mask |= 1 << i
return mask
@cache
def dfs(seat: int, i: int) -> int:
ans = 0
for mask in range(1 << n):
if (seat | mask) != seat or (mask & (mask << 1)):
continue
cnt = mask.bit_count()
if i == len(ss) - 1:
ans = max(ans, cnt)
else:
nxt = ss[i + 1]
nxt &= ~(mask << 1)
nxt &= ~(mask >> 1)
ans = max(ans, cnt + dfs(nxt, i + 1))
return ans
n = len(seats[0])
ss = [f(s) for s in seats]
return dfs(ss[0], 0)
复杂度分析
| 指标 | 值 |
|---|---|
| 时间 | complexity is O(m * 2^n * 2^n) due to enumerating all valid row states and transitions. Space complexity is O(2^n) for storing DP values per row. Both depend heavily on n, but m is small (<=8). |
| 空间 | Depends on the final approach |
面试官常问的追问
外企场景- question_mark
Do you recognize this as a state transition DP problem with bitmasking for seating constraints?
- question_mark
Can you generate all valid seating configurations per row efficiently without checking every permutation?
- question_mark
How would you ensure students in the current row do not see students diagonally in the previous row?
常见陷阱
外企场景- error
Failing to enforce that students in the current row cannot see upper-left or upper-right neighbors in the previous row.
- error
Not filtering out row configurations that place students in broken seats.
- error
Incorrectly counting adjacent students in the same row which violates the no-cheating rule.
进阶变体
外企场景- arrow_right_alt
Maximize students while also minimizing empty seats between them for social distancing enforcement.
- arrow_right_alt
Allow only one type of diagonal visibility and compute the new maximum seating arrangement.
- arrow_right_alt
Extend the classroom to 3D (multiple floors) while maintaining visibility constraints per floor.