剑指OFFER 顺时针打印矩阵

剑指OFFER 顺时针打印矩阵

试错记录

递归解(代码有错)

class Solution {
public:
    vector<int> res;
    void printSuround(vector<vector<int>> &m,int x,int y)
    {
        int size = m.size();
        if(m[x][y]==-1)return;
        while(x>=0 && y>=0 && x<size && y<size && m[x][y]!=-1)
        {
            res.push_back(m[x][y]);
            m[x][y]=-1;
            y++;
        }
        y--;
        x++;
        while(x>=0 && y>=0 && x<size && y<size && m[x][y]!=-1)
        {
            res.push_back(m[x][y]);
            m[x][y]=-1;
            x++;
        }
        x--;
        y--;
        while(x>=0 && y>=0 && x<size && y<size && m[x][y]!=-1)
        {
            res.push_back(m[x][y]);
            m[x][y]=-1;
            y--;
        }
        y++;
        x--;
        while(x>=0 && y>=0 && x<size && y<size && m[x][y]!=-1)
        {
            res.push_back(m[x][y]);
            m[x][y]=-1;
            x--;
        }
        x++;
        y++;
        printSuround(m,x,y);
    }

    vector<int> printMatrix(vector<vector<int>> matrix) {
        res.clear();
        if(matrix.size() == 0)return res;//如果矩阵空则返回一个空vector
        printSuround(matrix,0,0);
        return res;
    }
};

循环解(代码有错)

不使用递归,转换为循环,仍超时... 懵了

class Solution {
public:
    vector<int> res;
    pair<int,int> fac[4] = {{0,1},{1,0},{0,-1},{-1,0}};

    vector<int> printMatrix(vector<vector<int>> m) {
        res.clear();
        if(m.size() == 0)return res;//如果矩阵空则返回一个空vector
        if(m.size() == 1)
        {
            res.push_back(m[0][0]);
            return res;
        }
        int x = 0;
        int y = 0;
        int size = m.size();
        while(m[x][y] != -1)
        {
            for(int i=0;i<4;i++)
            {
                while(x>=0 && y>=0 && x<size && y<size && m[x][y] != -1)
                {
                    res.push_back(m[x][y]);
                    m[x][y] = -1;
                    x += fac[i].first;
                    y += fac[i].second;
                }
                x -= fac[i].first;
                y -= fac[i].second;
                x += fac[(i+1)%4].first;
                y += fac[(i+1)%4].second;
            }
        }
        return res;
    }
};

现在还没弄明白是哪个步骤这么耗时,复杂度应该是差不多,先放这,以后弄明了再补充

找出原因

算法的思路实际并没有问题,而是因为考虑少了一些特殊情况

出现超时其实是因为 当只输入单行或者单列时候出现了死循环(数组越界访问)

解决办法:

  • 在大while里面再次限制x,y的值,当旋转一周后,仍然没有矩阵元素可加入res数组中就直接结束,不再继续旋转(继续旋转可能会使得访问越界)

  • 前面的代码是使用-1来标记元素是否被访问过(这种方式有缺陷,如果矩阵的元素本身有-1存在就会混淆判断),下面改用了哈希表,在避免混淆的同时避免重复访问vector数组,效率得到了很大提升,相同的代码在leetcode上提交,运行速度简直恐怖.

    题目 54.Spiral Matrix
    Runtime: 0 ms, faster than 100.00% of C++ online submissions for Spiral Matrix.
    Memory Usage: 8.8 MB, less than 24.24% of C++ online submissions for Spiral Matrix.
    

下面给出正确代码:

class Solution {
public:
    vector<int> res;
    pair<int,int> fac[4] = {{0,1},{1,0},{0,-1},{-1,0}};//旋转因子
    map<pair<int,int>,bool> hash;
    vector<int> printMatrix(vector<vector<int>> m) {
        res.clear();
        if(m.size() == 0)return res;//如果矩阵空则返回一个空vector

        int x = 0;
        int y = 0;
        int x_size = m.size();//行数
        int y_size = m[0].size();//列数
        //这里存在短路,前面条件不满足就不查哈希表了
        while(x>=0 && y>=0 && x<x_size && y<y_size && !hash[pair<int,int>(x,y)])
        {
            for(int i=0;i<4;i++)//四个方向,旋转四次
            {
                //这里存在短路,前面条件不满足就不查哈希表了
                while(x>=0 && y>=0 && x<x_size && y<y_size && !hash[pair<int,int>(x,y)])
                {
                    res.push_back(m[x][y]);
                    hash[pair<int,int>(x,y)] = true;
                    x += fac[i].first;
                    y += fac[i].second;
                }
                x -= fac[i].first;
                y -= fac[i].second;//越界返回
                x += fac[(i+1)%4].first;
                y += fac[(i+1)%4].second;//前往下一个元素
            }
        }
        return res;
    }
};

其他题解

下面代码不是我写的,学习一下别人是怎么写的

从代码上看效率,不管是空间复杂度还是时间复杂度都是比较好的.但是逻辑需要很清晰才能写出来

class Solution {
public:
    vector<int> printMatrix(vector<vector<int>> matrix) {
        int row=matrix.size();
        int col=matrix[0].size();
        vector<int> result;
        if(row==0||col==0)
            return result;
        int left=0,right=col-1,top=0,btm=row-1;
        while(left<=right&&top<=btm)
            {
            for(int i=left;i<=right;i++)
                result.push_back(matrix[top][i]);
            if(top<btm)
                for(int i=top+1;i<=btm;i++)
                    result.push_back(matrix[i][right]);
            if(top<btm&&left<right)
                for(int i=right-1;i>=left;i--)
                    result.push_back(matrix[btm][i]);
            if(top+1<btm&&left<right)
                for(int i=btm-1;i>=top+1;i--)
                    result.push_back(matrix[i][left]);
            left++;right--;top++;btm--;
        }
        return result;
    }
};
原文地址:https://www.cnblogs.com/virgildevil/p/12188733.html