2024.1.4力扣每日一题——被列覆盖的最多行数

题目来源

力扣每日一题;题序:2397

我的题解

方法一 回溯+位运算优化

这道题一看就会想到使用回溯法,但是采用回溯法后如何判断有多少行被覆盖,直接计算矩阵时间复杂度较高,因此可以将0-1矩阵的每一行抽象为一个整数R,以及将选中列形成的整数L,然后根据位运算计算 R^L 是否等于R本身,若等于本身则表示该行被覆盖,然后在回溯过程中更新最终结果

时间复杂度:O(m× 2 n 2^n 2n)
空间复杂度:O(m)。矩阵的行转换为整数需要的空间

int ans = 0;

public int maximumRows(int[][] matrix, int numSelect) {
    int m = matrix.length, n = matrix[0].length;
    if (n <= numSelect) return m;
    int[] nums = new int[m];
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (matrix[i][j] == 1) nums[i] |= 1 << j;
        }
    }
    backTrace(n - 1, m, nums, numSelect);
    return ans;
}

public void backTrace(int n, int m, int[] nums, int numSelect) {
    // 当给定的列数选完或者矩阵的列遍历完,更新结果
    if (n < 0 || numSelect == 0) {
        int c = 0;
        //计算覆盖的行数
        for (int num : nums) if (num == 0) c++;
        ans = Math.max(ans, c);
        return;
    }
    //不选择第n列 并缩小列的范围
    backTrace(n - 1, m, nums, numSelect);
    // modify表示选中的列的二进制数对应的整数
    int modify = 0, index = 0;
    //把对应列上的1去除
    for (int i = 0; i < m; i++) {
        if (((nums[i] >> n) & 1) == 1) {
            nums[i] ^= 1 << n;
            modify |= 1 << i;
        }
    } 
    //选择第n列 并缩小列的范围
    backTrace(n - 1, m, nums, numSelect - 1);
    // 回退
    while (modify > 0 && index < m) {
        if ((modify & 1) == 1) {
            nums[index] |= 1 << n;
        }
        modify = modify >> 1;
        index++;
    }
}

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

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜菜的小彭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值