数据结构学习 jz29 顺时针打印矩阵

关键词:模拟

题目:螺旋遍历二维数组

简单题做了超过40分钟 调了很久 不好

方法一:

我自己做的。

思路:

xy_t:

记录xy的方向,往右走,往下走,往左走,往上走

t控制方向

cpp 复制代码
std::vector<std::vector<int>>xy_t{ {0,1},{1,0},{0,-1},{-1,0} };

isx:

true:轮到x方向动

false:轮到y方向动

cpp 复制代码
bool isx = false;

n_res m_res:

n_res:还没走过的行数(x方向)

m_res:还没走过的列数(y方向)

cpp 复制代码
int n_res = n, m_res = m;

res:

现在走的方向剩余的行数/列数。

cpp 复制代码
int res = isx ? n_res : m_res;

step:

现在走的这一行/这一列已经走过的步数。

记录结果,步数加一:

cpp 复制代码
result.push_back(array[x][y]);
step++;

如果step+1超过res,意味着这一行/这一列走到底了:

1、如果isx==true(在x方向上走了一列),那么m_res-1

2、如果isx==false(在y方向上走了一行),那么n_res-1

3、isx方向反转

4、改变t控制的方向

5、step归零

cpp 复制代码
            if (step + 1 > res)
            {
                n_res = isx ? n_res : n_res - 1;
                m_res = !isx ? m_res : m_res - 1;
                isx = !isx;
                t = (t + 1) % 4;
                step = 0;
            }

走下一步:

cpp 复制代码
            x = x + xy_t[t][0];
            y = y + xy_t[t][1];

比如:

先沿y方向走一行。

走完之后,n_res--

再沿x方向走一列。

走完之后,m_res--

循环这个过程直到所有数被走完。

复杂度计算:

时间复杂度O(nm)

空间复杂度O(1)

代码:

cpp 复制代码
class Solution {
public:
    std::vector<int> spiralArray(std::vector<std::vector<int>>& array) {
        std::vector<int> result;
        if (array.empty() || array[0].empty()) return result;
        int n = array.size(), m = array[0].size();
        int x = 0, y = 0;
        std::vector<std::vector<int>>xy_t{ {0,1},{1,0},{0,-1},{-1,0} };
        bool isx = false;
        int n_res = n, m_res = m;
        int step = 0;
        int t = 0;
        for (int i = 0; i < n * m; i++)
        {
            int res = isx ? n_res : m_res;
            result.push_back(array[x][y]);
            step++;
            if (step + 1 > res)
            {
                n_res = isx ? n_res : n_res - 1;
                m_res = !isx ? m_res : m_res - 1;
                isx = !isx;
                t = (t + 1) % 4;
                step = 0;
            }
            x = x + xy_t[t][0];
            y = y + xy_t[t][1];
        }
        return result;
    }
};

方法二:

看了k神的提示,弄了四面会活动的墙。显然比我原本的好。

思路:

四面墙:

l左墙

r右墙

t上墙

b下墙

cpp 复制代码
int l = 0, r = m - 1, t = 0, b = n - 1;

cut:

统计已经走过的格子的个数。

从左往右走:

碰到右墙就停止。

走完之后上面第一行已经走完,上墙往下移动一行,t++。

cpp 复制代码
            for (int i = l; i <= r; ++i)
            {
                cut++;
                result.push_back(array[t][i]);
            }
            if (cut >= m * n) break;
            t++;

从上往下走:

碰到下墙就停止。

走完之后右边第一列已经走完,右墙往左移动一列,r--。

cpp 复制代码
            for (int i = t; i <= b; ++i)
            {
                cut++;
                result.push_back(array[i][r]);
            }
            if (cut >= m * n) break;
            r--;

从右往左走:

碰到左墙就停止。

走完之后下面第一行已经走完,下墙往上移动一行,b--。

cpp 复制代码
            for (int i = r; i >= l; --i)
            {
                cut++;
                result.push_back(array[b][i]);
            }
            if (cut >= m * n) break;
            b--;

从下往上走:

碰到上墙就停止。

走完之后左边第一列已经走完,左墙往右移动一列,l++。

cpp 复制代码
            for (int i = b; i >= t; --i)
            {
                cut++;
                result.push_back(array[i][l]);
            }
            if (cut >= m * n) break;
            l++;

复杂度计算:

时间复杂度O(nm)

空间复杂度O(1)

代码:

cpp 复制代码
class Solution {
public:
    std::vector<int> spiralArray(std::vector<std::vector<int>>& array) {
        std::vector<int> result;
        if (array.empty() || array[0].empty()) return result;
        int n = array.size(), m = array[0].size();
        int l = 0, r = m - 1, t = 0, b = n - 1;
        int cut = 0;//统计已经放进result的个数
        while (true)
        {
            for (int i = l; i <= r; ++i)
            {
                cut++;
                result.push_back(array[t][i]);
            }
            if (cut >= m * n) break;
            t++;
            for (int i = t; i <= b; ++i)
            {
                cut++;
                result.push_back(array[i][r]);
            }
            if (cut >= m * n) break;
            r--;
            for (int i = r; i >= l; --i)
            {
                cut++;
                result.push_back(array[b][i]);
            }
            if (cut >= m * n) break;
            b--;
            for (int i = b; i >= t; --i)
            {
                cut++;
                result.push_back(array[i][l]);
            }
            if (cut >= m * n) break;
            l++;

        }

        return result;
    }
};
相关推荐
数智工坊2 分钟前
【数据结构-树与二叉树】4.6 树与森林的存储-转化-遍历
数据结构
好好学习天天向上~~2 分钟前
6_Linux学习总结_自动化构建
linux·学习·自动化
望舒51313 分钟前
代码随想录day25,回溯算法part4
java·数据结构·算法·leetcode
独好紫罗兰24 分钟前
对python的再认识-基于数据结构进行-a006-元组-拓展
开发语言·数据结构·python
铉铉这波能秀42 分钟前
LeetCode Hot100数据结构背景知识之集合(Set)Python2026新版
数据结构·python·算法·leetcode·哈希算法
踢足球09291 小时前
寒假打卡:2026-2-8
数据结构·算法
非凡ghost1 小时前
PowerDirector安卓版(威力导演安卓版)
android·windows·学习·软件需求
老赵说1 小时前
Java基础数据结构全面解析与实战指南:从小白到高手的通关秘籍
数据结构
铉铉这波能秀1 小时前
LeetCode Hot100数据结构背景知识之元组(Tuple)Python2026新版
数据结构·python·算法·leetcode·元组·tuple
代码游侠1 小时前
C语言核心概念复习——C语言基础阶段
linux·开发语言·c++·学习