力扣每日一题;题序:1349
参考:该作者
将每一行可以做的位置置为0,不可以做的置为1,则可以将每一行根据二进制转换为对应的值,然后遍历每一行的状态[0, 2 m 2^m 2m],然后先判断每个状态是否坐到了原本不可以坐的位置上,若坐到了不可以坐的位置上就直接跳过,否则就以此状态进行下一行的座位判断(也就是深度遍历)。
时间复杂度:O( m ∗ n ∗ 2 2 n m*n*2^{2n} m∗n∗22n)。状态数量共有 m × 2 n m×2^n m×2n种,计算一个状态需要消耗 n × 2 n n×2^n n×2n的时间。
空间复杂度:O( m ∗ 2 n m*2^n m∗2n)
class Solution {
int limitMask; //最大值
int[][] memo;//记忆数组
int[] notSeatMasks;//每一行对应的二进制值
public int maxStudents(char[][] seats) {
int n = seats.length, m = seats[0].length;
int maxCol = 1 << m;
this.limitMask = (1 << m) - 1;
this.notSeatMasks = new int[n + 1];
//根据原始数组构造每行的二进制值
for (int y = 0; y < n; y++) {
int res = 0;
for (int x = 0; x < m; x++) res |= (seats[y][x] & 1) << x;
notSeatMasks[y] = res;
}
this.memo = new int[n + 1][maxCol];
Arrays.fill(memo[n], 1);
return dfs(0, notSeatMasks[0]);
}
//深度优先遍历
private int dfs(int row, int notSeat) {
if (memo[row][notSeat] > 0) return memo[row][notSeat] - 1;
int fixMask = limitMask ^ notSeat;
int seating = (1 + notSeat) & fixMask;
int best = dfs(row + 1, notSeatMasks[row + 1]);
while (seating > 0) {
//计算seating坐法下这一行可以做的学生数量
int student = Integer.bitCount(seating);
//计算下一行的二进制值
int nextNotSeat = seating << 1 & limitMask | (seating >> 1) | notSeatMasks[row + 1];
//更新最优值
best = Math.max(best, student + dfs(row + 1, nextNotSeat));
//更新坐法
seating = ((seating >> 1 | seating | notSeat) + 1) & ~(seating >> 1) & fixMask;
}
memo[row][notSeat] = best + 1;
return best;
}
}
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈~