力扣-数组-特定顺序遍历二维数组

力扣-数组-特定顺序遍历二维数组

54 螺旋矩阵

54 螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1:
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]

提示:

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

按层模拟:不需要记录已经走过的路径,所以执行用时和内存消耗都相对较小
首先设定上下左右边界
其次向右移动到最右,此时第一行因为已经使用过了,可以将其从图中删去,体现在代码中就是重新定义上边界
判断若重新定义后,上下边界交错,表明螺旋矩阵遍历结束,跳出循环,返回答案
若上下边界不交错,则遍历还未结束,接着向下向左向上移动,操作过程与第一,二步同理
不断循环以上步骤,直到某两条边界交错,跳出循环,返回答案

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ans;
        if(matrix.empty()) return ans;
        int up = 0;
        int down = matrix.size() - 1;
        int left = 0;
        int right = matrix[0].size() - 1;
        while(true) {
            for (int i = left; i <= right; ++i) ans.push_back(matrix[up][i]);
            if (++up > down) break;
            for (int i = up; i <= down; ++i) ans.push_back(matrix[i][right]);
            if (--right < left) break;
            for (int i = right; i >= left; --i) ans.push_back(matrix[down][i]);
            if (--down < up) break;
            for (int i = down; i >= up; --i) ans.push_back(matrix[i][left]);
            if (++left > right) break;
        }
        return ans;
    }
};
  • 时间复杂度:O(mn),其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
  • 空间复杂度:O(1)。除了输出数组以外,空间复杂度是常数。

59 螺旋矩阵 II

59 螺旋矩阵 II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

示例 1:
1

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

示例 2:

输入:n = 1
输出:[[1]]

提示:

1 <= n <= 20

思路一致

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        if (n == 0) return res;
        int num = 1;
        int left = 0, right = n - 1;
        int up = 0, down = n - 1;
        while (left <= right && up <= down) {
            for (int i = left; i <= right; ++i) res[up][i] = num++;
            up++;
            if (up > down) break;
            for (int i = up; i <= down; ++i) res[i][right] = num++;
            right--;
            if(right < left) break;
            for (int i = right; i >= left; --i) res[down][i] = num++;
            down--;
            for (int i = down; i >= up; --i) res[i][left] = num++;
            left++;
        }
        return res;
    }
};

498 对角线遍历

498 对角线遍历

给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。

示例:

输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,4,7,5,3,6,8,9]
解释:
498

说明:

给定矩阵中的元素总数不会超过 100000 。

模拟行走路线

  1. 知道该对角线的行走方向。
  2. 确定对角线的起点元素

算法

  1. 初始化一个布尔变量 direction 表示当前对角线的方向。根据当前方向和尾部位置确定下一条对角线首部。最初 direction 为 1,方向向上。每条对角线遍历完成后更新 direction。

  2. 假设当前对角线首部为 matrix[i][j],根据方向遍历该对角线。
    向上的对角线,下一个元素是 matrix[i−1][j+1]。
    向下的对角线,下一个元素是 matrix[i+1][j−1]。

  3. 遍历当前对角线元素直到到达矩阵边界结束。

  4. 假设现在到达当前对角线的最后一个元素,寻找下一条对角线首部。注意:下面伪代码中方向是当前对角线方向。如果当前对角线方向是向上的,则下一条对角线是向下的;否则是下一条对角线是向上的。

  5. 继续处理对角线元素,当前对角线遍历结束时,使用当前方向和尾部位置找出下一条对角线首部。然后翻转方向,处理下一条对角线。

1

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
        if(matrix.empty()) return {};
        int N = matrix.size();
        int M = matrix[0].size();
        int row = 0, column = 0;
        int direction = 1; //初始化一个布尔变量direction表示当前对角线的方向  最初direction为1,方向向上
        vector<int> result(N*M, 0);
        int r = 0;
        while (row < N && column < M) {
            result[r++] = matrix[row][column];
            int new_row = row + (direction == 1 ? -1 : 1); // 方向 行
            int new_column = column + (direction == 1 ? 1 : -1); // 方向 列
            if (new_row < 0 || new_row == N || new_column < 0 || new_column == M) { // 边界条件
                if (direction == 1) {
                    row += (column == M - 1 ? 1 : 0);
                    column += (column < M - 1 ? 1 : 0);
                } else {
                    column += (row == N - 1 ? 1 : 0);
                    row += (row < N - 1 ? 1 : 0);
                }
                direction = 1 - direction;
            } else {
                row = new_row;
                column = new_column;
            }
        }
        return result;
    }
};
  • 时间复杂度:O(N⋅M),每个元素只处理一次。
  • 空间复杂度:O(1),不使用额外空间。注意:输出数组空间不计入空间复杂度,因为这是题目要求的空间。空间复杂度应该指除了最终数组以外的空间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

国服最强貂蝉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值