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


    题目描述

    给你一个大小为 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;

    代码实现如下:

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. class Solution3 {
    4. public int numSpecial(int[][] mat) {
    5. Boolean[] columnMap = new Boolean[mat[0].length];
    6. int res = 0;
    7. for (int i = 0; i < mat.length; i++) {
    8. List list = new ArrayList<>();
    9. for (int j = 0; j < mat[i].length; j++) {
    10. int v = mat[i][j];
    11. int vIndex = i * mat[0].length + j;
    12. if (v == 1) {
    13. list.add(vIndex);
    14. }
    15. }
    16. if (list.size() == 1) {
    17. int j = list.get(0) % mat[0].length;
    18. if (columnMap[j] == null) {
    19. int count = 0;
    20. for (int x = 0; x < mat.length; x++) {
    21. if (mat[x][j] == 1) {
    22. count++;
    23. }
    24. }
    25. columnMap[j] = (count == 1);
    26. }
    27. if (columnMap[j]) {
    28. res++;
    29. }
    30. }
    31. }
    32. return res;
    33. }
    34. public static void main(String[] args) {
    35. Solution3 solution = new Solution3();
    36. System.out.println(solution.numSpecial(new int[][]{
    37. {0, 0, 0, 0, 0, 0, 1, 0, 0},
    38. {0, 0, 0, 0, 0, 0, 0, 0, 0},
    39. {0, 0, 0, 0, 0, 0, 0, 0, 0},
    40. {0, 0, 0, 0, 0, 0, 0, 0, 1},
    41. {0, 0, 0, 1, 0, 1, 0, 0, 0}
    42. }));
    43. }
    44. }

    结果发现耗时还是挺高的,翻看了其他代码实现,直接做3次 m*n的遍历耗时反而是最低的,这块超过我的预期。

    具体思路如下:

    • 准备rowMap和columnMap;
    • 第一次遍历,计算rowMap中每一行出现1的次数;
    • 第二次遍历,计算columnMap中每一列出现1的次数;
    • 第三次遍历,如果mat[i][j]==1 && rowMap[i]==1 && columnMap[j]==1,则执行res++;
    • 最后返回res。

    代码实现如下:

    1. class Solution {
    2. public int numSpecial(int[][] mat) {
    3. int row = mat.length;
    4. int column = mat[0].length;
    5. int[] rowMap = new int[row];
    6. int[] columnMap = new int[column];
    7. int res = 0;
    8. for (int i = 0; i < row; i++) {
    9. int count = 0;
    10. for (int j = 0; j < column; j++) {
    11. if (mat[i][j] == 1) {
    12. count++;
    13. }
    14. }
    15. rowMap[i] = count;
    16. }
    17. for (int j = 0; j < column; j++) {
    18. int count = 0;
    19. for (int i = 0; i < row; i++) {
    20. if (mat[i][j] == 1) {
    21. count++;
    22. }
    23. }
    24. columnMap[j] = count;
    25. }
    26. for (int i = 0; i < row; i++) {
    27. for (int j = 0; j < column; j++) {
    28. if (mat[i][j] == 1 && rowMap[i] == 1 && columnMap[j] == 1) {
    29. res++;
    30. }
    31. }
    32. }
    33. return res;
    34. }
    35. public static void main(String[] args) {
    36. Solution solution = new Solution();
    37. System.out.println(solution.numSpecial(new int[][]{
    38. {0, 0, 0, 0, 0, 0, 1, 0, 0},
    39. {0, 0, 0, 0, 0, 0, 0, 0, 0},
    40. {0, 0, 0, 0, 0, 0, 0, 0, 0},
    41. {0, 0, 0, 0, 0, 0, 0, 0, 1},
    42. {0, 0, 0, 1, 0, 1, 0, 0, 0}
    43. }));
    44. }
    45. }

     


    总结

    这道题有点超过我的意料,3次遍历耗时反而最低;如果有更加高效、简洁的代码实现欢迎回复。

  • 相关阅读:
    【金融项目】尚融宝项目(十)
    残差网络(ResNet)
    王学岗ffmpeg编译
    SQL——左连接(Left join)、右连接(Right join)、内连接(Inner join)
    打印流详解
    SpringBoot日志
    Arthas(阿尔萨斯)使用手册
    STM32F4X UCOSIII软件定时器
    在 Spring Data应用程序中使用Criteria条件查询
    java实验报告1:JDK的安装配置及基本输出练习
  • 原文地址:https://blog.csdn.net/weiliuhong1/article/details/126686996