2023.12.26力扣每日一题——参加考试的最大学生数

2023.12.26

      • 题目来源
      • 我的题解
        • 方法一 深度优先遍历+记忆化搜索

题目来源

力扣每日一题;题序:1349

我的题解

方法一 深度优先遍历+记忆化搜索

参考:该作者

将每一行可以做的位置置为0,不可以做的置为1,则可以将每一行根据二进制转换为对应的值,然后遍历每一行的状态[0, 2 m 2^m 2m],然后先判断每个状态是否坐到了原本不可以坐的位置上,若坐到了不可以坐的位置上就直接跳过,否则就以此状态进行下一行的座位判断(也就是深度遍历)。

时间复杂度:O( m ∗ n ∗ 2 2 n m*n*2^{2n} mn22n)。状态数量共有 m × 2 n m×2^n m×2n种,计算一个状态需要消耗 n × 2 n n×2^n n×2n的时间。
空间复杂度:O( m ∗ 2 n m*2^n m2n)

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;
    }
}

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈~

你可能感兴趣的:(java,力扣每日一题,leetcode,算法,职场和发展)