


目录
方法一:哈希表+位运算
思路
- 首先遍历矩阵的每一行,将每行转化为一个整数表示(通过位运算),并记录每个整数对应的行索引。
- 然后检查是否存在某一行全为 0 的情况,若有则直接返回该行索引。
- 接着遍历已记录的整数对,看是否存在两个整数按位与为 0 的情况,如果找到这样的一对,就返回对应的两行索引。
解题方法
通过位运算处理每行数据,利用哈希表记录信息,然后通过双重循环查找满足条件的行对。
时间复杂度
主要时间消耗在两层循环上,循环次数为已记录整数个数的平方,即O(n²)(n其中为不同整数的个数,通常小于矩阵的行数)。
空间复杂度
使用了一个哈希表来存储整数和行索引,空间复杂度为O(n)。
Code
class Solution {
public List<Integer> goodSubsetofBinaryMatrix(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
Map<Integer, Integer> int2idx = new HashMap<>();
for (int i = 0; i < m; i++) {
int x = 0;
for (int j = 0; j < n; j++) {
x |= (grid[i][j] << j);
}
if (x == 0) {
return List.of(i);
}
int2idx.put(x, i);
}
for (int x : int2idx.keySet()) {
for (int y : int2idx.keySet()) {
if ((x & y) == 0) {
int i = int2idx.get(x);
int j = int2idx.get(y);
if (i > j) {
return List.of(j, i);
} else {
return List.of(i, j);
}
}
}
}
return List.of();
}
}

方法二:二进制
思路
看到这一题,首先可以注意到,每一行的二进制表示与每一列的二进制表示进行按位与操作,得到的结果就是该行中1的个数。因此,我们可以通过计算每一行的二进制表示与相应的列的二进制表示进行按位与操作,然后将结果相加,得到的结果就是该行中1的个数。
解题方法
1.首先,我们需要遍历整个矩阵,计算每一列的和。这可以通过位运算来实现,将每一行的二进制表示与相应的列的二进制表示进行按位与操作,然后将结果相加。
2.接下来,我们需要检查每一列是否可以找到一个子集,其大小不超过该列和的一半。这可以通过位运算来实现,将每一列的二进制表示与相应的列的二进制表示进行按位与操作,然后将结果与该列的二进制表示进行比较。如果结果等于该列的二进制表示,那么说明可以找到一个子集,其大小不超过该列和的一半。
3.最后,我们需要检查每一对键是否相与为0。这可以通过位运算来实现,将每一对键的按位与操作结果与0进行比较。如果结果等于0,那么说明可以找到一个好子集,返回这两个行号。
时间复杂度
O(n2)
空间复杂度
O(n2)
Code
public class Solution{
public List<Integer> goodSubsetofBinaryMatrix(int[][] grid) {
Map<Integer, Integer> maskToIdx = new HashMap<>();
for (int i = 0; i < grid.length; i++) {
int mask = 0;
for (int j = 0; j < grid[i].length; j++) {
mask |= grid[i][j] << j;
}
if (mask == 0) {
return List.of(i);
}
maskToIdx.put(mask, i);
}
for (Map.Entry<Integer, Integer> e1 : maskToIdx.entrySet()) {
for (Map.Entry<Integer, Integer> e2 : maskToIdx.entrySet()) {
if ((e1.getKey() & e2.getKey()) == 0) {
int i = e1.getValue();
int j = e2.getValue();
return i < j ? List.of(i, j) : List.of(j, i);
}
}
}
return List.of();
}
}

823

被折叠的 条评论
为什么被折叠?



