力扣每日一题;题序: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++;
}
}
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈~