ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-10-27 23:05:06  阅读:239  来源: 互联网

标签:Java mat int 矩阵 003 ++ length 数组 LeetCode


目录

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

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;
    }

在这里插入图片描述

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

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;
    }

在这里插入图片描述

三、翻转图像

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;
    }

在这里插入图片描述

四、旋转图像

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;
            }
        }
    }

在这里插入图片描述

五、转置矩阵

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;
    }

在这里插入图片描述

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

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;
    }

在这里插入图片描述

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

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
在这里插入图片描述

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;
    }

在这里插入图片描述

八、二维网格迁移

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;
    }

在这里插入图片描述

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

    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;
    }

在这里插入图片描述

标签:Java,mat,int,矩阵,003,++,length,数组,LeetCode
来源: https://blog.csdn.net/Victor_Seven/article/details/121003590

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有