【LeetCode解题报告】《算法基础003_矩阵》- Java

目录

一、最富有客户的资产数量

1.题目

1672.最富有客户的资产数量

给你一个 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i​​​​​ 位客户在第 j 家银行托管的资产数量。
客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户。
返回最富有客户所拥有的 资产总量 。
m == accounts.length
n == accounts[i].length
1 <= m, n <= 50
1 <= accounts[i][j] <= 100

2.分析

这道题简单来说就是返回二维数组中,各个子数组所有数之和的最大值。

  1. 二维数组的行数(数组个数):accounts.length
  2. 二维数组的列数(对应子数组的长度):accounts[i].length

3.代码

    public int maximumWealth(int[][] accounts) {
        int max = 0;
        for (int i = 0;i < accounts.length;i++){
            int sum = 0;
            for (int j = 0;j < accounts[i].length;j++){
                sum += accounts[i][j];
            }
            if (sum > max){
                max = sum;
            }
        }
        return max;
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

二、二进制矩阵中的特殊位置

1.题目

1582.二进制矩阵中的特殊位置

给你一个大小为 rows x cols 的矩阵 mat,其中 mat[i][j] 是 0 或 1,请返回 矩阵 mat 中特殊位置的数目 。
特殊位置 定义:如果 mat[i][j] == 1 并且第 i 行和第 j 列中的所有其他元素均为 0(行和列的下标均 从0 开始 ),则位置 (i, j) 被称为特殊位置。
rows == mat.length
cols == mat[i].length
1 <= rows, cols <= 100
mat[i][j] 是 0 或 1

2.分析

这道题首先想到的思路就是:

  • 遍历所有的位置,当有一个位置为1,则再分别遍历该位置对应行和对应列,如果都不为1,则计数加1。接着遍历下一个点。

然而,再仔细想一下,发现了一些规律:

  • 根据给出的特殊位置的定义,每行最多只能有1个特殊位置,且每列也最多只能有1个特殊位置。
    所以只要判定某个为1的位置不是特殊位置,该行该列的其他位置在遍历时都可以直接跳过,以减少遍历次数。

3.代码

    public int numSpecial(int[][] mat) {
        //定义遍历的下标
        int j,i = 0;
        //矩阵行数
        int rows = mat.length;
        //矩阵列数
        int cols = mat[i].length;
        //特殊位置个数
        int count = 0;
        for (i = 0;i < rows;i++){
            inner:
            for (j = 0;j < cols;j++){
                if (mat[i][j] == 1){
                    //遍历i行的所有列,除特殊位置外还有位置为1,则直接跳出当前行循环
                    for (int col = 0;col < cols;col++){
                        if (col == j){
                            continue;
                        } else if (mat[i][col] == 1){
                            break inner;
                        }
                    }
                    //遍历j列的所有行,除特殊位置外还有位置为1,则直接跳出当前行循环
                    for (int row = 0;row < rows;row++){
                        if (row == i){
                            continue;
                        } else if (mat[row][j] == 1){
                            break inner;
                        }
                    }
                    //如果为特殊位置,计数加1
                    count++;
                }
            }
        }
        return count;
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

三、翻转图像

1.题目

832.翻转图像

给定一个二进制矩阵 A,我们想先水平翻转图像,然后反转图像并返回结果。
水平翻转图片就是将图片的每一行都进行翻转,即逆序。例如,水平翻转 [1, 1, 0] 的结果是 [0, 1, 1]。
反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。例如,反转 [0, 1, 1] 的结果是 [1, 0, 0]。
1 <= A.length = A[0].length <= 20
0 <= A[i][j] <= 1

2.分析

以其中一个子数组水平翻转并翻转图像为例:

  1. 定义两个变量 j = 0 和 k = image[ i ].length - 1,分别为数组的首尾下标。
  2. 水平翻转:其实就是数组的首尾交换,交换后首下标加1,尾下标减1,直到 j < k 为止。
  3. 反转图像:因为数组中的数只有 0 和 1,所以可以通过水平翻转后,用 (1 - 水平翻转后的值) 来实现。

3.代码

    public int[][] flipAndInvertImage(int[][] image) {
        for (int i = 0;i < image.length;i++){
            int j = 0;
            int k = image[i].length - 1;
            while (j <= k){
                int t = image[i][j];
                image[i][j] = 1- image[i][k];
                image[i][k] = 1 - t;
                j++;
                k--;
            }
        }
        return image;
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

四、旋转图像

1.题目

48.旋转图像

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
matrix.length == n
matrix[i].length == n
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000

2.分析

这道题自己想得有些复杂,参考了力扣大佬的思路:

  • 顺时针旋转90° = 转置矩阵的元素以左右对称的形式互换

3.代码

    public void rotate(int[][] matrix) {
        int n = matrix.length;
        //先变成转置矩阵
        for (int i = 0;i < n;i++){
            for (int j = 0;j < i;j++){
                int t = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = t;
            }
        }
        //转置矩阵左右对称交换元素得到旋转90度后的矩阵
        for (int i = 0;i < n;i++){
            for (int j = 0;j < n / 2;j++){
                int t = matrix[i][j];
                matrix[i][j] = matrix[i][n - j - 1];
                matrix[i][n - j - 1] = t;
            }
        }
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

五、转置矩阵

1.题目

867.转置矩阵

给你一个二维整数数组 matrix, 返回 matrix 的 转置矩阵 。
矩阵的 转置 是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。
m == matrix.length
n == matrix[i].length
1 <= m, n <= 1000
1 <= m * n <= 105
-109 <= matrix[i][j] <= 109

2.分析

转置矩阵放到二维数组中,实际上就是行列下标的互换:

  1. 定义二维数组,用来存放转置矩阵的元素。
  2. 原矩阵的行下标作为转置矩阵的列下标,原矩阵的列下标作为转置矩阵的行下标,将元素存到转置矩阵的二维数组中。(行变列,列变行)

3.代码

    public int[][] transpose(int[][] matrix) {
        int j,i = 0;
        //原矩阵行数
        int rows = matrix.length;
        //原矩阵列数
        int cols = matrix[i].length;
        //转置矩阵
        int[][] trans = new int[cols][rows];
        for (i = 0;i < rows;i++){
            for (j = 0;j < cols;j++){
                trans[j][i] = matrix[i][j];
            }
        }
        return trans;
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

六、将一维数组变成二维数组

1.题目

2022.将一维数组变成二维数组

给你一个下标从 0 开始的一维整数数组 original 和两个整数 m 和 n 。你需要使用 original 中 所有 元素创建一个 m 行 n 列的二维数组。
original 中下标从 0 到 n - 1 (都 包含 )的元素构成二维数组的第一行,下标从 n 到 2 * n - 1(都包含)的元素构成二维数组的第二行,依此类推。
请你根据上述过程返回一个 m x n 的二维数组。如果无法构成这样的二维数组,请你返回一个空的二维数组。
1 <= original.length <= 5 * 104
1 <= original[i] <= 105
1 <= m, n <= 4 * 104

2.分析

  1. 在遍历一维数组前,先判断该数组是否能构成m 行 n 列的二维数组。能将一维数组构成二维数组,必定符合:一维数组长度 original.length = m * n
  2. 定义二维数组以及初始行和列下标 row,col
  3. 遍历一维数组,将该数组的元素存放到二维数组中,每次存放完一个元素,col 加1。
  4. 当 col = n 时,说明当前行已经放满,则换到下一行的起始位置,即 row加1,col = 0,直到遍历结束。

3.代码

    public int[][] construct2DArray(int[] original, int m, int n) {
        if (m * n != original.length){
            return new int[][]{};
        }
        //定义一个二维数组
        int[][] result = new int[m][n];
        //二维数组的起始行和列下标
        int row = 0;
        int col = 0;
        for (int i = 0;i < original.length;i++){
            result[row][col] = original[i];
            col++;
            if (col == n){
                row++;
                col = 0;
            }
        }
        return result;
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

七、判断矩阵经轮转后是否一致

1.题目

1886.判断矩阵经轮转后是否一致

给你两个大小为 n x n 的二进制矩阵 mat 和 target 。
现以90度顺时针轮转矩阵 mat中的元素若干次,如果能够使mat与target一致,返回 true;否则,返回 false 。
n == mat.length == target.length
n == mat[i].length == target[i].length
1 <= n <= 10
mat[i][j] 和 target[i][j] 不是 0 就是 1
【LeetCode解题报告】《算法基础003_矩阵》- Java

2.分析

这道题我只能做出来,但是更优的方法实在是想不到了。

思路:

  1. 每次旋转90°,所以最多旋转3次。
  2. 判断两个矩阵是否一样的方法:通过将2个矩阵的同一行元素以字符串形式判断是否相同(每一行就是一个数组,即将同一行的数组元素变成字符串来比较,用 Arrays.toString(int[] a) 方法实现)。
  3. 判断两个矩阵是否一样(逐行判断数组元素的字符串是否相同):
    如果判断有其中一行不相同,则旋转90°,并跳到下一循环。
    如果旋转了3次还有不同,则返回false。
    只要判断其中有一次全部相同,则返回true。

3.代码

    public boolean findRotation(int[][] mat, int[][] target) {
        int rows = mat.length;
        //最多90°旋转3次
        outer:
        for(int n = 0;n <= 3;n++){
            for (int i = 0;i < rows;i++){
                //如果有一行不相等,旋转90°
                if (!Arrays.toString(mat[i]).equals(Arrays.toString(target[i]))){
                    for (int j = 0;j < rows;j++){
                        for (int k = 0;k < j;k++){
                            int t = mat[j][k];
                            mat[j][k] = mat[k][j];
                            mat[k][j] = t;
                        }
                    }
                    for (int j = 0;j < rows;j++){
                        for (int k = 0;k < rows / 2;k++){
                            int t = mat[j][k];
                            mat[j][k] = mat[j][rows - k - 1];
                            mat[j][rows - k - 1] = t;
                        }
                    }
                    continue outer;
                }
            }
            //循环结束也没有break,说明每行数据都一致,则返回true
            return true;
        }
        //经过三次循环也没有一次元素全部相同,返回false
        return  false;
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

八、二维网格迁移

1.题目

1260.二维网格迁移

给你一个 m 行 n 列的二维网格 grid 和一个整数 k。你需要将 grid 迁移 k 次。
每次「迁移」操作将会引发下述活动:
位于 grid[i][j] 的元素将会移动到 grid[i][j + 1]。
位于 grid[i][n - 1] 的元素将会移动到 grid[i + 1][0]。
位于 grid[m - 1][n - 1] 的元素将会移动到 grid[0][0]。
请你返回 k 次迁移操作后最终得到的 二维网格。
m == grid.length
n == grid[i].length
1 <= m <= 50
1 <= n <= 50
-1000 <= grid[i][j] <= 1000
0 <= k <= 100

2.分析

方法一:每次遍历往后迁移一步,直到迁移k步

  • 一开始我就是用的这种比较简单的方法。但是,虽然通过了,执行效率却不高。
  • 我知道应该想办法在迁移的时候就一次迁移到k步的位置,但是迟迟找不到规律所在,后来总算让我想到了~

方法二:将迁移后的二维数组元素存到定义的一维数组中

  1. 定义一维数组,遍历的时候,将二维数组的元素赋值到一维数组迁移k步后的位置(迁移前:二维数组的(0,0)对应一维数组的下标0位置)
  2. 一维数组长度为 :行数 * 列数(m * n)
  3. 防止 k 大于一维数组长度出现数组越界,当 k 大于等于一维数组长度,k需要再从下标0开始数:所以 k %= (行数 * 列数)
  4. 遍历一维数组存入集合List时,可以模仿遍历二维数组的方式,但取值是取一维数组的值

3.代码

方法一:每次遍历往后迁移一步,直到迁移k步

    public List<List<Integer>> shiftGrid(int[][] grid, int k) {
        int a = 0;
        int m = grid.length;
        int n = grid[a].length;
        for (int i = 1;i <= k;i++){
            //将二维网格最后一个数取出暂存
            int tem = grid[m - 1][n - 1];
            for (a = 0;a < m;a++){
                for (int b = 0;b < n;b++){
                    //遍历位置的数和暂存tem的数交换
                    int t = grid[a][b];
                    grid[a][b] = tem;
                    tem = t;
                }
            }
        }
        //存到List集合
        List<Integer> list = null;
        List<List<Integer>> list2 = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            list = new ArrayList<>();
            for (int j = 0; j < n; j++) {
                list.add(grid[i][j]);
            }
            list2.add(list);
        }
        return list2;
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

方法二:将迁移后的二维数组元素存到定义的一维数组中

    public List<List<Integer>> shiftGrid(int[][] grid, int k) {
        int a = 0;
        int m = grid.length;
        int n = grid[a].length;
        //把二维数组转换成一维数组
        int[] g = new int[m * n];
        for (int i = 0;i < m;i++){
            for (int j = 0;j < n;j++){
                //防止迁移大于 m * n步
                if (k >= g.length){
                    k %= g.length;
                }
                g[k] = grid[i][j];
                k++;
            }
        }
        //存到List集合
        List<Integer> list = null;
        List<List<Integer>> list2 = new ArrayList<>();
        for (int i = 0; i < m; i++) {
            list = new ArrayList<>();
            for (int j = 0; j < n; j++) {
                list.add(g[j + i * n]);
            }
            list2.add(list);
        }
        return list2;
    }

【LeetCode解题报告】《算法基础003_矩阵》- Java

上一篇:Opencv之图像混合(Java)


下一篇:Java Arrays.deepToString()用法及代码示例