题意概述

  • 给定一个m*n的矩阵
  • 要求按照螺旋的顺序返回矩阵中的所有元素

方法一:方向数组转向

思路与具体做法

  • 用一个方向数组d来进行矩阵遍历过程中的转向
  • 当遍历过程中超过边界或遍历到已访问元素时就改变方向,具体做法是先按原来遍历方向尝试着进行遍历,若出矩阵范围或已访问,说明应该转向
  • 每次转向按照右->下->左->上->右的顺序进行选择,用标记变量flag进行标记,每次转向中自增然后对四取余即实现对这个四个方向的闭环选择
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int> > &matrix) {
        vector<int>ans;
        int m=matrix.size(),n=matrix[0].size();//矩阵的大小 
        if(m==0)return ans;//空螺旋矩阵直接返回 
		int d[4][2]={{0,1},{1,0},{0,-1},{-1,0}};//右下左上   
		int x=0,y=0,flag=0;//x,y数组下标,flag标记转向   
		for(int i=0;i<m*n;i++){
			ans.push_back(matrix[x][y]);
			matrix[x][y]=INT_MAX;//标记已访问 
			int newx=x+d[flag][0],newy=y+d[flag][1];//尝试到下一位置 
			if(newx<0||newx>=m||newy<0||newy>=n||matrix[newx][newy]==INT_MAX)flag=(++flag)%4;//该位置超出矩阵范围或已访问,说明应该转向 
			x+=d[flag][0],y+=d[flag][1];//到达正确的下一位置 
		} 
		return ans;
    }
};

时间复杂度和空间复杂度分析

  • 时间复杂度:O(mn)O(m*n)O(mn),遍历了整个二维数组
  • 空间复杂度:O(mn)O(m*n)O(mn),遍历结果数组ans共m*n个元素

方法二:模拟

思路与具体做法

  • 模拟螺旋矩阵的路径。
  • 初始位置是矩阵左上角,两层循环,外层循环在遍历元素<=全部元素的时候就继续遍历,内层循环,设立四个循环分别从右->下->左->上四个方向不断枚举
  • 外层循环走一遍具体表现是螺旋矩阵绕一圈,每次令层数加一 alt
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int> > &matrix) {
        vector<int>ans;
        int m=matrix.size(),n=matrix[0].size();//矩阵的大小 
        if(m==0)return ans;//空螺旋矩阵直接返回 
        int cn=0,layer=0;//cn用于计数,layer记录螺旋矩阵的层数 
		while(cn<m*n){
			for(int i=layer;i<n-layer;i++){//向右,初始从[0][0~n-1] 
				ans.push_back(matrix[layer][i]);cn++;
			}
            if(cn>=m*n)break;
			for(int i=layer+1;i<m-layer;i++){//向下,初始从[1~m-1][n-1] 
				ans.push_back(matrix[i][n-1-layer]);cn++;
			}
            if(cn>=m*n)break;
			for(int i=n-2-layer;i>=layer;i--){//向左,初始从[m-1][n-2~0] 
				ans.push_back(matrix[m-1-layer][i]);cn++;
			}
			for(int i=m-2-layer;i>layer;i--){//向上,初始从[m-2~1][0] 
				ans.push_back(matrix[i][layer]);cn++;
			}
			layer++;//层数加1			
		} 
		return ans;
    }
};

时间复杂度和空间复杂度分析

  • 时间复杂度:O(mn)O(m*n)O(mn),遍历了整个二维数组
  • 空间复杂度:O(mn)O(m*n)O(mn),遍历结果数组ans共m*n个元素