备战秋招DAY0-今日力扣-矩阵

1.矩阵置零(难度等级:中)

重点是要考虑时间复杂度和空间复杂度。

直观上,我们首先需要遍历一次矩阵,并通过一个额外空间来记录哪些位置上出现了0。然后,我们需要再次遍历一次矩阵,通过这个额外空间来“传染”其他位置的元素。

如何优化这个额外空间的大小呢?

这里给出次优解(易理解和记忆):

class Solution {
    public void setZeroes(int[][] matrix) {
        boolean rowZero = false;
        boolean colZero = false;
        //判断第一列是否出现0元素
        for(int i=0; i<matrix.length; i++){
            if(matrix[i][0] == 0){
                colZero = true;
            } 
        }
        //判断第一行是否出现0元素
        for(int i=0; i<matrix[0].length; i++){
            if(matrix[0][i] == 0){
                rowZero = true;
            } 
        }
        //遍历矩阵,将0值记录到第一行或第一列中
        for(int i=1; i<matrix.length; i++){
            for(int j=1; j<matrix[0].length; j++){
                if(matrix[i][j] == 0){
                    matrix[i][0] = matrix[0][j] = 0;
                }
            }
        }
        //其他元素传染传染
        for(int i=1; i<matrix.length; i++){
            for(int j=1; j<matrix[0].length; j++){
                if(matrix[i][0] == 0 || matrix[0][j] == 0){
                    matrix[i][j] = 0;
                }
            }
        }
        //原来第一行或第一列的0元素传染
        if(colZero){
            for(int i=0; i<matrix.length; i++){
                matrix[i][0] = 0;
            }
        }
        if(rowZero){
            for(int i=0; i<matrix[0].length; i++){
                matrix[0][i] = 0;
            }
        }
    }
}

2. 螺旋矩阵(难度等级:中)

这道题其实比较巧妙的思想是 将其看成“多层”的矩阵,然后你会发现:对于每一层来说,遍历的路线都是一致的耶!都是从左到右->从上到下->从右到左->从下到上。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        int row = matrix.length;
        int col = matrix[0].length;
        //分别表示矩阵每一“层”的边界(左,右,上,下)
        int left = 0, right = col - 1, top = 0, bottom = row - 1;
        while(left <= right && top <= bottom){
           for(int i=left; i<=right; i++){
                res.add(matrix[top][i]); //从左到右
           }
           for(int j=top+1; j<=bottom; j++){
                res.add(matrix[j][right]); //从上到下
           }
           if(left<right && top<bottom){ //到最内层了就不用再执行后面的操作了
                for(int i=right-1; i>=left; i--){
                    res.add(matrix[bottom][i]);
                }
                for(int j=bottom-1; j>top; j--){
                    res.add(matrix[j][left]);
                }
           }
           left++;
           right--;
           top++;
           bottom--;
        }
        return res;
    }
}

3.旋转图像(难度等级:中)

本题的关键在于:不允许使用额外的矩阵,因此如何减小空间复杂度较为重要。

最为浅显的方式是 构造一个数组来缓存要操作的元素,以避免被覆盖,但是这种方式空间复杂度达到了N^2

这里提供一种较好理解和记忆的思路:顺时针旋转其实可以拆解为两次翻转操作——先水平翻转,再延着对角线翻转。

class Solution {
    public void rotate(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        //水平翻转
        for(int i=0; i<m/2; i++){
            for(int j=0; j<n; j++){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[m-i-1][j];
                matrix[m-i-1][j] = temp;
            }
        }
        //对角线翻转
        for(int i=0; i<m; i++){
            for(int j=0; j<i; j++){
                int temp2 = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp2;
            }
        }
    }
}

4.搜索二维矩阵(难度等级:中)

这一题其实难度不高,除了暴力解法外,首先能想到的就是对 行/列 的二分查找,但这种方式只能利用到行或者列其中一种的二分特性,并不是效率最高的。

其实仔细观察不难发现,我们可以构建一个以矩阵左下角为起点,变化的矩阵右上角为终点的“滑动矩阵”,通过查询结果结合矩阵的特性,来自适应地调整右上角的位置,直到最终查询到target。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length;
        int n = matrix[0].length;
        int x = 0;
        int y = n-1;
        while(y>=0 && x<m){
            if(target == matrix[x][y]){
                return true;
            }
            if(target > matrix[x][y]){
                x++;
                continue;
            }
            if(target < matrix[x][y]){
                y--;
                continue;
            }
        }
        return false;
    }
}

总结

其实从Hot 100中的矩阵题不难发现,关键点集中于考察空间复杂度。所以做题时仔细挖掘技巧,只要找到了技巧,再将技巧“翻译成”代码即可。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值