数据结构学习 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;
    }
};
相关推荐
Miqiuha4 分钟前
lock_guard和unique_lock学习总结
java·数据库·学习
嵌入式AI的盲1 小时前
数组指针和指针数组
数据结构·算法
一 乐1 小时前
学籍管理平台|在线学籍管理平台系统|基于Springboot+VUE的在线学籍管理平台系统设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·学习
加油,旭杏2 小时前
【中间件学习】fastCG介绍和使用
学习·nginx·fastcgi
limengshi1383922 小时前
通信工程学习:什么是TFTP简单文件传输协议
网络·网络协议·学习·信息与通信
GFCGUO3 小时前
ubuntu18.04运行OpenPCDet出现的问题
linux·python·学习·ubuntu·conda·pip
reyas3 小时前
B树系列解析
数据结构·b树
Indigo_code3 小时前
【数据结构】【顺序表算法】 删除特定值
数据结构·算法
丝丝不是土豆丝4 小时前
学习 CSS 新的属性 conic-gradient 实现环形进度条
学习
阿史大杯茶4 小时前
Codeforces Round 976 (Div. 2 ABCDE题)视频讲解
数据结构·c++·算法