【数组】二进制矩阵中的特殊位置

题目描述

给你一个大小为 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次遍历耗时反而最低;如果有更加高效、简洁的代码实现欢迎回复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值