题目描述
给你一个大小为 rows x cols 的矩阵 mat,其中 mat[i][j] 是 0 或 1,请返回 矩阵 mat 中特殊位置的数目 。
特殊位置 定义:如果 mat[i][j] == 1 并且第 i 行和第 j 列中的所有其他元素均为 0(行和列的下标均 从 0 开始 ),则位置 (i, j) 被称为特殊位置。
示例 1:
输入:mat = [[1,0,0],
[0,0,1],
[1,0,0]]
输出:1
解释:(1,2) 是一个特殊位置,因为 mat[1][2] == 1 且所处的行和列上所有其他元素都是 0
解题思路
这道题是一道简单题目,核心还是找到高效的解决方案;
- 使用二维转一维思路,int row = mat.length; int column = mat[0].length; mat[i][j] 对应的位置是 int index = i * column + j ;
- 遍历数组mat,
- 如果mat[i][j]==1 ,则执行 int vIndex = i * column + j ; list.add(vIndex);
- 如果list.size() == 1,说明 第i行满足条件;
- 接着计算第j列是否满足条件, 如果满足条件则res++;
- 最终返回res;
代码实现如下:
import java.util.ArrayList;
import java.util.List;
class Solution3 {
public int numSpecial(int[][] mat) {
Boolean[] columnMap = new Boolean[mat[0].length];
int res = 0;
for (int i = 0; i < mat.length; i++) {
List<Integer> list = new ArrayList<>();
for (int j = 0; j < mat[i].length; j++) {
int v = mat[i][j];
int vIndex = i * mat[0].length + j;
if (v == 1) {
list.add(vIndex);
}
}
if (list.size() == 1) {
int j = list.get(0) % mat[0].length;
if (columnMap[j] == null) {
int count = 0;
for (int x = 0; x < mat.length; x++) {
if (mat[x][j] == 1) {
count++;
}
}
columnMap[j] = (count == 1);
}
if (columnMap[j]) {
res++;
}
}
}
return res;
}
public static void main(String[] args) {
Solution3 solution = new Solution3();
System.out.println(solution.numSpecial(new int[][]{
{0, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 1, 0, 1, 0, 0, 0}
}));
}
}
结果发现耗时还是挺高的,翻看了其他代码实现,直接做3次 m*n的遍历耗时反而是最低的,这块超过我的预期。
具体思路如下:
- 准备rowMap和columnMap;
- 第一次遍历,计算rowMap中每一行出现1的次数;
- 第二次遍历,计算columnMap中每一列出现1的次数;
- 第三次遍历,如果mat[i][j]==1 && rowMap[i]==1 && columnMap[j]==1,则执行res++;
- 最后返回res。
代码实现如下:
class Solution {
public int numSpecial(int[][] mat) {
int row = mat.length;
int column = mat[0].length;
int[] rowMap = new int[row];
int[] columnMap = new int[column];
int res = 0;
for (int i = 0; i < row; i++) {
int count = 0;
for (int j = 0; j < column; j++) {
if (mat[i][j] == 1) {
count++;
}
}
rowMap[i] = count;
}
for (int j = 0; j < column; j++) {
int count = 0;
for (int i = 0; i < row; i++) {
if (mat[i][j] == 1) {
count++;
}
}
columnMap[j] = count;
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (mat[i][j] == 1 && rowMap[i] == 1 && columnMap[j] == 1) {
res++;
}
}
}
return res;
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.numSpecial(new int[][]{
{0, 0, 0, 0, 0, 0, 1, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 1, 0, 1, 0, 0, 0}
}));
}
}
总结
这道题有点超过我的意料,3次遍历耗时反而最低;如果有更加高效、简洁的代码实现欢迎回复。