【算法笔记】5.LeetCode-Hot100-矩阵专项

1. 矩阵置零(t73)

中等难度,题目示例如下:

lua 复制代码
给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用原地算法。

示例 1:
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

示例 2:
输入:matrix = [[0,1,2,0],[3,4,5,2],[1,3,1,5]]
输出:[[0,0,0,0],[0,4,5,0],[0,3,1,0]]

思路分析:看到这题,一个朴素的思想是,只要遇到 0 的元素就去查询同行同列,但这样操作搜索的复杂度过高。看题解可以采用一个标记数组,相当于复制一个矩阵,如果遇到有元素为0,就将其行和列标记为true,最后再遍历一次矩阵,对标记的部分置零。

ini 复制代码
class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        vector<int> row(m), col(n);
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (!matrix[i][j]) {
                    row[i] = col[j] = true;
                }
            }
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (row[i] || col[j]) {
                    matrix[i][j] = 0;
                }
            }
        }
    }
};

2. 螺旋矩阵(t54**)

中等难度,题目示例如下:

lua 复制代码
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

思路分析:可以从两个角度去考虑,第一个角度是从纯数理的方式去找规律,比如转向等操作可以通过对宽高取模来判断,但理解起来较抽象;第二个角度是直接从矩阵结构**入手,用四个变量去跟踪矩阵的边界,下面以这个思路进行求解。

ini 复制代码
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ans;
        if (matrix.empty()) return ans;

        int rows = matrix.size();
        int cols = matrix[0].size();
        int up = 0, down = rows - 1;
        int left = 0, right = cols - 1;

        while (true) {
            // 向右
            for (int i = left; i <= right; i++) {
                ans.push_back(matrix[up][i]);
            }
            up++;
            if (up > down) break;

            // 向下
            for (int i = up; i <= down; i++) {
                ans.push_back(matrix[i][right]);
            }
            right--;
            if (right < left) break;

            // 向左
            for (int i = right; i >= left; i--) {
                ans.push_back(matrix[down][i]);
            }
            down--;
            if (down < up) break;

            // 向上
            for (int i = down; i >= up; i--) {
                ans.push_back(matrix[i][left]);
            }
            left++;
            if (left > right) break;
        }

        return ans;
    }
};

3. 旋转图像(t48)

中等难度,题目示例如下:

lua 复制代码
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

示例 2:
输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

思路分析:这题最简单的思路就是直接找旋转的图像的规律,仔细观察就可以发现,旋转这个操作,等价于对角线翻转+左右翻转。下面稍微注意的是,做对角线翻转只需要遍历矩阵的上三角。

ini 复制代码
class Solution {
public:
    void rotate(vector<vector<int>>& matrix) {
        int rows = matrix.size();
        int cols = matrix[0].size();
        
        // 对角线翻转
        for (int i = 0; i < rows; i++){
            for (int j = i; j < cols; j++){
                swap(matrix[i][j], matrix[j][i]);
            }
        }
        
        // 左右翻转
        for (int i = 0; i < rows; i++){
            for (int j = 0; j < cols / 2; j++){
                swap(matrix[i][j], matrix[i][cols - 1 - j]);
            }
        }
    }
};

4. 搜索二维矩阵 II(t240)

中等难度,题目示例如下:

lua 复制代码
编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

每行的元素从左到右升序排列。
每列的元素从上到下升序排列。

示例:
输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true

思路分析:这道题直接用暴力法很容易求解,可以直接按先列后行的顺序搜索,一旦遇到大于 target 的值,就提前跳出,节省时间。

ini 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int rows = matrix.size();
        int cols = matrix[0].size();
        for (int i = 0; i < rows; i++){
            for (int j = 0; j < cols; j++){
                if (matrix[i][j] == target) return true;
                else if (matrix[i][j] > target) break; 
            }
        }
        return false;
    }
};

题目中,每行每列都已经是排序好的,因此显然存在更优方案,看了用户 Krahets 的题解恍然大悟,把矩阵逆时针旋转 45°,就变成了类似二叉搜索树的结构。

图源:leetcode.cn/problems/se...

因此,可以从矩阵的左下角出发,如果左下角大于target,则往上移动一行,如果小于target,则可以直接往右搜索。

arduino 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int i = matrix.size() - 1, j = 0;
        while(i >= 0 && j < matrix[0].size())
        {
            if(matrix[i][j] > target) i--;
            else if(matrix[i][j] < target) j++;
            else return true;
        }
        return false;
    }
};
相关推荐
conkl35 分钟前
构建 P2P 网络与分布式下载系统:从底层原理到安装和功能实现
linux·运维·网络·分布式·网络协议·算法·p2p
Shan120541 分钟前
递归算法的一些具体应用
算法
paopaokaka_luck3 小时前
婚纱摄影管理系统(发送邮箱、腾讯地图API、物流API、webSocket实时聊天、协同过滤算法、Echarts图形化分析)
vue.js·spring boot·后端·websocket·算法·echarts
白熊1884 小时前
【大模型LLM】梯度累积(Gradient Accumulation)原理详解
人工智能·大模型·llm
愚戏师4 小时前
机器学习(重学版)基础篇(算法与模型一)
人工智能·算法·机器学习
F_D_Z5 小时前
【PyTorch】图像多分类项目部署
人工智能·pytorch·python·深度学习·分类
OEC小胖胖6 小时前
渲染篇(二):解密Diff算法:如何用“最少的操作”更新UI
前端·算法·ui·状态模式·web
找不到、了6 小时前
Java排序算法之<归并排序>
算法·排序算法
香蕉可乐荷包蛋6 小时前
排序算法 (Sorting Algorithms)-Python示例
python·算法·排序算法
Sylvia-girl6 小时前
排序查找算法,Map集合,集合的嵌套,Collections工具类
java·算法·排序算法