矩阵

766托普利茨矩阵(数组、矩阵、小内存大数据)

给你一个 m x n 的矩阵 matrix 。如果这个矩阵是托普利茨矩阵,返回 true ;否则,返回 false 。
如果矩阵上每一条由左上到右下的对角线上的元素都相同,那么这个矩阵是 托普利茨矩阵 。

示例 1:
输入:matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]]
输出:true
解释:
在上述矩阵中, 其对角线为:
“[9]”, “[5, 5]”, “[1, 1, 1]”, “[2, 2, 2]”, “[3, 3]”, “[4]”。
各条对角线上的所有元素均相同, 因此答案是 True 。

示例 2:
输入:matrix = [[1,2],[2,2]]
输出:false
解释:
对角线 “[1, 2]” 上的元素不同。

提示:
m == matrix.length
n == matrix[i].length
1 <= m, n <= 20
0 <= matrix[i][j] <= 99

进阶:
如果矩阵存储在磁盘上,并且内存有限,以至于一次最多只能将矩阵的一行加载到内存中,该怎么办? 如果矩阵太大,以至于一次只能将不完整的一行加载到内存中,该怎么办?
Related Topics 数组

思路1:将第一行与第一列的元素进行遍历,设x,y,满足 0<=x<matrix.length -1,0<=y<matrix[0].length-1,且matrix[x][y]==matrix[x+1][y+1];

class Solution {
    public boolean isToeplitzMatrix(int[][] matrix) {
        for (int x = 0; x < matrix.length - 1; x++) {
            for (int y = 0; y < matrix[0].length - 1; y++) {
                if (matrix[x][y] != matrix[x + 1][y + 1]) {
                    return false;
                }
            }
        }
        return true;
    }
}

考虑到进阶的问题一:一次最多只能将矩阵的一行加载到内存中,我们将每一行复制到一个连续数组中,随后在读取下一行时,就与内存中此前保存的数组进行比较。
以下的实现还有点偏差,内存中必须存储两行元素

class Solution {
    public boolean isToeplitzMatrix(int[][] matrix) {
        // 从内存中加载一行
        int[] row = matrix[0];
        // 对列数进行循环
        for (int r = 1; r < matrix.length; r++) {
            for (int c = 1; c < matrix[0].length; c++) {
                // 读取的下一行一个元素需要与前一行的前一个元素相同
                if(matrix[r][c] != row[c-1]) {
                    return false;
                }
            }
            //如果相同,赋值给内存中的唯一一行元素
            row = matrix[r];
        }
        return true;
    }
}

对于进阶问题二,一次只能将不完整的一行加载到内存中,我们将整个矩阵竖直切分成若干子矩阵,并保证两个相邻的矩阵至少有一列或一行是重合的,然后判断每个子矩阵是否符合要求。
还是以分治的思想

566. 重塑矩阵 [二维数组与一维数组转换]

在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。
给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。
如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

示例 1:
输入:
nums =
[[1,2],
[3,4]]
r = 1, c = 4
输出:
[[1,2,3,4]]
解释:
行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。

示例 2:
输入:
nums =
[[1,2],
[3,4]]
r = 2, c = 4
输出:
[[1,2],
[3,4]]
解释:
没有办法将 2 * 2 矩阵转化为 2 * 4 矩阵。 所以输出原矩阵。

注意:
给定矩阵的宽和高范围在 [1, 100]。
给定的 r 和 c 都是正数。
Related Topics 数组

思路1:直接迁移的方法,申请一个ans[r][c]的矩阵,将nums中的元素放入ans数组中,时间复杂度O(r*c)


class Solution {
    public int[][] matrixReshape(int[][] nums, int r, int c) {
        // 边界判断
        if (r * c != nums[0].length * nums.length) {
            return nums;
        }
        int ans[][] = new int[r][c];
        int cNums = nums[0].length;
        for (int i = 0; i < nums.length; i++) {
            for (int j = 0; j < nums[0].length; j++) {
            	// 将原矩阵的元素 映射到新矩阵上
                ans[(i * cNums + j) / c][(i * cNums + j) % c] = nums[i][j];
            }
        }
        return ans;
    }
}

原来以为通关了,直到我看到了这个答案:
其实两者的思想是一致的,都是利用了一维数据上的元素位置 与二维数组上元素位置的映射关系,但代码更易阅读

matrix[x/c][x%c] = nums[x];
其中c就是二维数组的列数,x为一维数组中的索引位置

class Solution {
    public int[][] matrixReshape(int[][] nums, int r, int c) {
        // 边界判断
        if (r * c != nums[0].length * nums.length) {
            return nums;
        }
        int ans[][] = new int[r][c];
        int rNums = nums.length;
        int cNums = nums[0].length;
        // 这里直接采用一维数组的思想,将一维数组作为转换的中介,代码更易阅读
        for (int i = 0; i < rNums * cNums; i++) {
            ans[i / c][i % c] = nums[i / cNums][i % cNums];
        }
        return ans;
    }
}

二分查找(74. 搜索二维矩阵)

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。

示例 1:
​​在这里插入图片描述
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

示例 2:
在这里插入图片描述
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false

提示:

m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-10^4 <= matrix[i][j], target <= 10^4

思路

首先每行的数据从左到右依次增大,下面行的数据都比上面行的数据大。比起“杨氏矩阵”简单了一些。其中一种思路就是可以将二维矩阵转换为一维数组,然后根据一维数据的位置计算二维数组的位置

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
    	// 获取矩阵的行数和列数
        int m = matrix.length;
        int n = matrix[0].length;
        // 边界值考虑
        if (target < matrix[0][0] || target > matrix[m - 1][n - 1]) {
            return false;
        }
        // 二分查找
        int left = 0, right = m * n - 1, mid;
        while (left <= right) {
            mid = (left+right) >> 1 ;
            // 根据一维数组映射二维数组,mid/n就是这个数所在的行,mid % n就是这个数所在的列
            int midVal= matrix[mid / n][mid % n];
            if (target == midVal) {
                return true;
            } else if (target < midVal) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        return false;
    }
}

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:38.2 MB, 在所有 Java 提交中击败了11.09%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值