跳转至

矩阵

约 853 个字 244 行代码 1 张图片 预计阅读时间 7 分钟

矩阵置零

题目描述

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0

示例

Text Only
输入:matrix = [[1,1,1],[1,0,1],[1,1,1]]
输出:[[1,0,1],[0,0,0],[1,0,1]]

输入: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]]

说明

  • m == matrix.length
  • n == matrix[0].length
  • 1 <= m, n <= 200
  • -2^31 <= matrix[i][j] <= 2^31 - 1

算法解析

这道题使用 原地算法 来节省空间:

  1. 核心思想 :利用矩阵的第一行和第一列来记录需要置零的行和列

  2. 算法步骤

  • 遍历矩阵,找到所有0元素

  • 将0元素所在行的第一个元素和所在列的第一个元素设为0

  • 再次遍历矩阵,根据第一行和第一列的标记置零

  1. 具体实现
  • 使用flag_col0标记第一列是否需要置零

  • 从第二列开始遍历,将0元素的行首和列首标记为0

  • 从下往上、从右往左遍历,根据标记置零

  1. 时间复杂度 :O(mn) - 需要遍历矩阵两次

  2. 空间复杂度 :O(1) - 只使用常数额外空间

C++
#define itn int
#define nit int
#define nti int
#define tin int
#define tni int
#define retrun return
#define reutrn return
#define rutren return
#define INF 0x3f3f3f3f
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;

class Solution
{
public:
    void setZeroes(vector<vector<int>> &matrix)
    {
        bool flag_col0 = false;
        for (int i = 0; i < matrix.size(); i++)
        {
            // 任意一行起始列为 0 标记为 true,最后这一列和 i 行会为 0
            if (!matrix[i][0])
                flag_col0 = true;

            for (int j = 1; j < matrix[0].size(); j++)
                if (!matrix[i][j])
                    matrix[i][0] = matrix[0][j] = 0;
        }

        for (int i = matrix.size() - 1; i >= 0; i--)
        {
            for (int j = 1; j < matrix[0].size(); j++)
                if (!matrix[i][0] || !matrix[0][j])
                    matrix[i][j] = 0;

            if (flag_col0)
                matrix[i][0] = 0;
        }
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // 构造测试用例:matrix = [[1,1,1],[1,0,1],[1,1,1]]
    vector<vector<int>> matrix = {
        {1, 1, 1},
        {1, 0, 1},
        {1, 1, 1}
    };

    cout << "原始矩阵:" << endl;
    for (const auto &row : matrix) {
        for (int val : row)
            cout << val << ' ';
        cout << endl;
    }

    Solution().setZeroes(matrix);

    cout << "置零后的矩阵:" << endl;
    for (const auto &row : matrix) {
        for (int val : row)
            cout << val << ' ';
        cout << endl;
    }

    return 0;
}

螺旋矩阵

题目描述

给你一个 m x n 的矩阵,请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例

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

输入: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]

说明

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

算法解析

这道题使用 模拟法 按照螺旋路径遍历矩阵:

  1. 核心思想 :模拟螺旋遍历的过程,按照右、下、左、上的顺序移动

  2. 算法步骤

  • 定义四个方向:右(0,1)、下(1,0)、左(0,-1)、上(-1,0)

  • 按照螺旋顺序遍历矩阵

  • 遇到边界或已访问元素时改变方向

  1. 具体实现
  • 使用dx、dy表示当前移动方向

  • 访问当前位置后标记为已访问(-101)

  • 检查下一个位置是否有效,无效则改变方向

  1. 时间复杂度 :O(mn) - 需要访问矩阵中的每个元素

  2. 空间复杂度 :O(1) - 只使用常数额外空间(不考虑输出数组)

C++
#define itn int
#define nit int
#define nti int
#define tin int
#define tni int
#define retrun return
#define reutrn return
#define rutren return
#define INF 0x3f3f3f3f
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;

class Solution
{
public:
    vector<int> spiralOrder(vector<vector<int>> &matrix)
    {
        vector<int> ans;
        int n = matrix.size(), m = matrix[0].size(), size = n * m;
        int i = 0, j = 0, dx = 0, dy = 1, tmp = 0;
        while (size--)
        {
            ans.push_back(matrix[i][j]);
            matrix[i][j] = -101;
            if (i + dx < n && i + dx >= 0 && j + dy < m && j + dy >= 0 && matrix[i + dx][j + dy] != -101)
                i += dx, j += dy;
            else
                tmp = dy, dy = -dx, dx = tmp, i += dx, j += dy;
        }

        return ans;
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // 构造测试用例:matrix = [[1,2,3],[4,5,6],[7,8,9]]
    vector<vector<int>> matrix = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };

    cout << "原始矩阵:" << endl;
    for (const auto &row : matrix) {
        for (int val : row)
            cout << val << ' ';
        cout << endl;
    }

    vector<int> res = Solution().spiralOrder(matrix);

    cout << "螺旋遍历结果: ";
    for (int val : res)
        cout << val << ' ';
    cout << endl;

    return 0;
}

旋转图像

给定一个 n x n 的二维矩阵表示一个图像,请将图像顺时针旋转 90 度。必须原地旋转,不能使用额外空间。

C++
#define itn int
#define nit int
#define nti int
#define tin int
#define tni int
#define retrun return
#define reutrn return
#define rutren return
#define INF 0x3f3f3f3f
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;

class Solution
{
public:
    void rotate(vector<vector<int>> &matrix)
    {
        for (int i = 0; i < matrix[0].size(); i++)
            for (int j = 0; j < matrix[0].size() - i; j++)
                swap(matrix[i][j], matrix[matrix[0].size() - 1 - j][matrix[0].size() - 1 - i]);

        for (int i = 0; i < matrix[0].size() / 2; i++)
            for (int j = 0; j < matrix[0].size(); j++)
                swap(matrix[i][j], matrix[matrix[0].size() - i - 1][j]);
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    vector<vector<int>> matrix(n, vector<int>(n));
    for (auto &row : matrix)
        for (auto &val : row)
            cin >> val;

    Solution().rotate(matrix);

    for (const auto &row : matrix) {
        for (int val : row)
            cout << val << ' ';
        cout << '\n';
    }

    return 0;
}

搜索二维矩阵 II

给你一个满足下述属性的 m x n 整数矩阵:

  • 每行的整数从左到右按升序排列
  • 每列的整数从上到下按升序排列

给你一个整数 target,请你判断 target 是否存在于矩阵中。

C++
#define itn int
#define nit int
#define nti int
#define tin int
#define tni int
#define retrun return
#define reutrn return
#define rutren return
#define INF 0x3f3f3f3f
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;

class Solution
{
public:
    bool searchMatrix(vector<vector<int>> &matrix, int& target)
    {
        int x = 0, y = matrix[0].size() - 1;

        while (x < matrix.size() && y >= 0)
        {
            if (matrix[x][y] == target)
                return true;
            if (matrix[x][y] > target)
                --y;
            else
                ++x;
        }

        return false;
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int m, n, target;
    cin >> m >> n;
    vector<vector<int>> matrix(m, vector<int>(n));
    for (auto &row : matrix)
        for (auto &val : row)
            cin >> val;
    cin >> target;

    cout << (Solution().searchMatrix(matrix, target) ? "true" : "false") << '\n';

    return 0;
}

评论