首页 > 试题广场 >

顺时针打印矩阵

[编程题]顺时针打印矩阵
  • 热度指数:989113 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵:
[[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]
则依次打印出数字
[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]
数据范围:
0 <= matrix.length <= 100
0 <= matrix[i].length <= 100

示例1

输入

[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]

输出

[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]
示例2

输入

[[1,2,3,1],[4,5,6,1],[4,5,6,1]]

输出

[1,2,3,1,1,1,6,5,4,4,5,6]
推荐
/*解题思路:顺时针打印就是按圈数循环打印,一圈包含两行或者两列,在打印的时候会出现某一圈中只包含一行,要判断从左向右打印和从右向左打印的时候是否会出现重复打印,同样只包含一列时,要判断从上向下打印和从下向上打印的时候是否会出现重复打印的情况*/
class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector<int>res;
        res.clear();
        int row=matrix.size();//行数
        int collor=matrix[0].size();//列数
        //计算打印的圈数
        int circle=((row<collor?row:collor)-1)/2+1;//圈数
        for(int i=0;i<circle;i++){
            //从左向右打印
            for(int j=i;j<collor-i;j++)
                res.push_back(matrix[i][j]);          
            //从上往下的每一列数据 
            for(int k=i+1;k<row-i;k++)
                res.push_back(matrix[k][collor-1-i]);
            //判断是否会重复打印(从右向左的每行数据) 
            for(int m=collor-i-2;(m>=i)&&(row-i-1!=i);m--) 
                res.push_back(matrix[row-i-1][m]); 
            //判断是否会重复打印(从下往上的每一列数据)
            for(int n=row-i-2;(n>i)&&(collor-i-1!=i);n--) 
                res.push_back(matrix[n][i]);}
        return res;
    }
};


编辑于 2015-09-07 13:31:21 回复(55)
import java.util.ArrayList;
public class Solution {
    ArrayList  a=new ArrayList();   new一个数组 以便下面函数能调用 
    public ArrayList printMatrix(int [][] matrix) {
       int tR=0;
       int tC=0;
       int dR=matrix.length-1;
       int dC=matrix[0].length-1;
        while(tR<=dR&&tC<=dC){ 左上边界最多到达右下边界 用于判断是否还是剥圈打印
       printEdge(matrix,tR++,tC++,dR--,dC--); 
        }
      return a;
    }
    public  void printEdge(int [][] m,int tR,int tC,int dR,int dC){
        if(tR==dR){    先判断是否只是一横行 如果是 打印该横行的列(通常用于内圈)
            for(int i=tC;i<=dC;i++){
                a.add(m[tR][i]);
            }
        }
        else if(tC==dC){  再判断是否只是一竖列 如果是 打印该横行的列(通常用于内圈
            for(int i=tR;i<=dR;i++){
                a.add(m[i][tC]);
            }
        }
        else {
            int curC=tC;用2个变量储存 用于判断当前位置
            int curR=tR;
            while(curC!=dC){      当前位置未到达当前行的最右列 --》往右去
                a.add(m[tR][curC]);
            curC++;
            }
            while(curR!=dR){      当前位置未到达当前列的最底行 --》往下去
                a.add(m[curR][dC]);
                curR++;
            }
            while(curC!=tC){      当前位置未到达当前行的最左列 --》往左去
                a.add(m[dR][curC]);
                curC--;
            }
            while(curR!=tR){      当前位置未到达当前列的最顶行 --》往上去
                a.add(m[curR][tC]);
                curR--;
            }
        }
    }
}

这个思路个人觉得看起来比上面的都要清晰 虽然较长 但是其实分析起来很简单 ,就是一个剥圈的函数,这个函数 核心就是 左上点和右下点 每次走完剥圈函数之后 左上角坐标++,右下角-- 往圈内移 如果觉得好 可以点点顶上去 让别人也看到

发表于 2018-02-07 22:00:44 回复(13)
//借鉴的二楼的代码,对二楼的代码进行了部分判断条件的修改
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 top = 0, left = 0, right = col-1, bottom = row-1;
        
        while(top <= bottom && left<= right){
            //left to right
            for(int i = left; i <= right; ++i) result.push_back(matrix[top][i]);
            //top tp bottom
            for(int i = top+1; i <= bottom; ++i) result.push_back(matrix[i][right]);
            //right to left
            for(int i = right-1; i >= left && top < bottom; --i) result.push_back(matrix[bottom][i]);
            //bottom to top
            for(int i = bottom-1; i > top && right > left; --i) result.push_back(matrix[i][left]);
            ++top; ++left; --right; --bottom;
        }
        return result;
    }
};

发表于 2017-06-21 11:25:04 回复(14)
/*
		 * 采用旋转魔方的方式 一次取一行,然后旋转
		 */
		public ArrayList<Integer> printMatrix_2(int[][] matrix) {
			ArrayList<Integer> al = new ArrayList<>();
			int row = matrix.length;
			while (row != 0) {
				for (int i = 0; i < matrix[0].length; i++) {
					al.add(matrix[0][i]);
				}
				if (row == 1)
					break;
				matrix = turn(matrix);
				row = matrix.length;
			}
			return al;
		}

		private int[][] turn(int[][] matrix) {
			// TODO 自动生成的方法存根
			int col = matrix[0].length;
			int row = matrix.length;
			int[][] newMatrix = new int[col][row - 1];
			for (int j = col - 1; j >= 0; j--) {
				for (int i = 1; i < row; i++) {
					newMatrix[col - 1 - j][i - 1] = matrix[i][j];
				}
			}
			return newMatrix;
		}



public ArrayList<Integer> printMatrix_1(int[][] matrix) {
			ArrayList<Integer> al = new ArrayList<>();
			int row = matrix.length;
			if (row == 0)
				return al;
			int col = matrix[0].length;
			// 短的边/2,向上取整
			int circle = ((row > col ? col : row) + 1) / 2;
			for (int i = 0; i < circle; i++) {

				// 从左向右打印,j=i; j<col-i,
				// 这一行的前i个已经在第i圈从下往上被打印,故j=i
				// 倒数i个都已经在第i圈从上往下被打印,故j=col-i-1<col-i
				for (int j = i; j < col - i; j++)
					al.add(matrix[i][j]);

				// 从上往下打印,j=i+1;j<row-i,
				// 这一列的前i+1个已经在从左向右打印时被打印,故j=i+1
				// 倒数i个已经在第i圈从右往左被打印,故j=row-i-1<row-i
				for (int j = i + 1; j < row - i; j++)
					al.add(matrix[j][col - i - 1]);

				// 从右往左打印,j=col-i-2;j>=i&&row-i-1!=i;,
				// 这一行倒数i个已经在第i圈从上往下被打印
				// 这一行倒数第i+1个已经在从上往下时被打印,故j=col-1-(i+1)=col-i-2
				// 这一行的前i个已经在从下往上时被打印,故j=i>=i
				// 当第i圈为0时即从未由上往下打印时,col有多列时,会造成重复打印,故判断row-i-1!=i以避免
				for (int j = col - i - 2; j >= i && row - i - 1 != i; j--)
					al.add(matrix[row - i - 1][j]);

				// 从下往上打印,j=row-i-2;j>i&&col-i-1!=i,
				// 这一列倒数i个已经在第i圈从右往作被打印
				// 这一列倒数第i+1个已经在从右往左时被打印,故j=row-1-(i+1)=row-i-2
				// 这一列的前i个已经在第i圈从左往右时被打印,
				// 这一列的第i+1个已经在本圈从左往右被打印,故j=i+1>i
				// 当第i圈为0时即从未由右向左打印时,row有多行时,会造成重复打印,故判断col-i-1!=i以避免
				for (int j = row - i - 2; j > i && col - i - 1 != i; j--)
					al.add(matrix[j][i]);
			}
			return al;
		}

编辑于 2017-06-08 21:13:48 回复(2)
/*
* 1.选坐标为(0,0),(1,1)...的点记为(start,start)为开始坐标,下一圈开始坐标为(start+1,start+1)
* 2.判断是否进入下一圈(即是否打印完成)的条件是row>start*2 && column>start*2
* 3.打印一圈的左上角坐标为(start,start),右下角的坐标为(column-start-1,row-start-1)
* 4.根据一圈左上角和右下角坐标判断“从左到右”,“从上到下”,“从右到左”,“从下到上”哪些用打印,哪些不用
*/

class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        if (matrix.empty()) {
            return matrix[0];
        }
        int row = static_cast<int>(matrix.size()) ;
        int column = static_cast<int>(matrix[0].size()) ;
        int start = 0;
        vector<int> result;
        result.clear();
        
        while (column > start*2 && row > start*2) {
            int endX = column - 1 - start;
            int endY = row - 1 - start;
            //从左到右打印一行
            for (int i=start; i<=endX; i++) {
                result.push_back(matrix[start][i]);
            }
            //从上到下打印一行
            if (start <endY) {
                for (int i=start+1; i<=endY; i++) {
                    result.push_back(matrix[i][endX]);
                }
            }
            //从右到左打印一行
            if (start < endX && start < endY) {
                for (int i=endX-1; i>=start; i--) {
                    result.push_back(matrix[endY][i]);
                }
            }
            //从下到上打印一行
            if (start<endX && start<endY-1) {
                for (int i=endY-1; i>=start+1; i--) {
                    result.push_back(matrix[i][start]);
                }
            }
            start++;
        }
        return result;
    }
};


编辑于 2015-10-23 16:14:54 回复(8)
/**
 * @description 顺时针打印矩阵
 * @author GongchuangSu
 * @since 2016.09.03
 * @explain 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 
 *                    1 2 3 4 
 *                    5 6 7 8 
 *                    9 10 11 12 
 *                    13 14 15 16 
 *          则依次打印出数字
 *                    1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
 */
import java.util.*;

public class Solution{
	ArrayList<Integer> list = new ArrayList<>();
	
    public ArrayList<Integer> printMatrix(int [][] matrix) {
    	int rows = matrix.length;
		int columns = matrix[0].length;
		int start = 0;
		while(rows > start*2 && columns > start*2){
			printMatrixInCircle(matrix, rows, columns, start);
			start++;
		}
        return list;
    }
	
	/**
	 * 功能:打印一圈
	 */
	public void printMatrixInCircle(int [][] matrix, int rows, int columns, int start){
		// 从左到右打印一行
		for(int i = start; i < columns - start; i++)
			list.add(matrix[start][i]);
		// 从上到下打印一列
		for(int j = start + 1; j < rows - start; j++)
			list.add(matrix[j][columns - start - 1]);
		// 从右到左打印一行
		for(int m = columns - start - 2; m >= start && rows - start - 1 > start; m--)
			list.add(matrix[rows - start - 1][m]);
		// 从下到上打印一列
		for(int n = rows - start - 2; n >= start + 1 && columns - start - 1 > start; n--)
			list.add(matrix[n][start]);
	}
}

发表于 2016-09-03 15:11:54 回复(12)
思路:
分为两个步骤:
1. 打印一圈
  1. 从左到右打印一行(这是一定有的)
  2. 当有两行及以上时,存在从上到下打印
  3. 当有两行及以上并有两列及以上时,存在从右到左
  4. 当有两列并有三行及以上时,存在从下到上打打印
2. 起点进入下一圈,即进入下一个循环
初始几点为(0, 0), 打印一圈后有(1, 1), 再打印一圈为(2, 2)
都存在行数 > 起点 * 2 并且列数 > 起点 * 2
简单来说就是, 如果把二维数组等分为四个部分 中点都为中心,那么起点肯定都位于左上部分。根据这个条件可以判断是否还有圈数

# -*- coding:utf-8 -*-
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        if not matrix:
            return []
        columns = len(matrix[0])
        rows = len(matrix)
        
        def printMatrixCircle(start):
            endRow = rows - 1 - start
            endColumn = columns - 1 - start
            
            # 从左到右打印一行
            for y in range(start, endColumn + 1):
                result.append(matrix[start][y])
                
            # 从上到下打印一列
            if endRow > start:
                for x in range(start + 1, endRow + 1):
                    result.append(matrix[x][endColumn])
                    
            # 从右到左打印一行
            if endColumn > start and endRow > start:
                for y in range(endColumn - 1, start - 1, -1):
                    result.append(matrix[endRow][y])
            
            # 从下到上打印
            if endRow > start + 1 and endColumn > start:
                for x in range(endRow - 1, start, -1):
                    result.append(matrix[x][start])
        
        start = 0
        result = []
        while columns > start * 2 and rows > start * 2:
            printMatrixCircle(start)
            start += 1
       	
        
        return result

编辑于 2016-07-25 09:45:26 回复(0)
前进,转弯,...

class Solution {
    int n, m;
    vector<vector<bool> > v;
    bool judge(int i, int j){
        return 0 <= i && i < n && 0 <= j && j < m && !v[i][j];
    }
public:
     vector<int> printMatrix(vector<vector<int> > a) {
        vector<int> r;
        if(!(n = a.size()) || !(m = a[0].size())) return r;
        v = vector<vector<bool> >(n, vector<bool>(m, false));
        const int D[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int i = 0, j = 0, d = 0, T = m * n;
        while(T--){
            r.push_back(a[i][j]);
            v[i][j] = true;
            if(!judge(i + D[d][0], j + D[d][1])) (++d) %= 4; //转弯
            i += D[d][0], j += D[d][1];//前进
        }
        return r;
    }
};

编辑于 2017-05-17 19:23:43 回复(6)
# -*- coding:utf-8 -*-
class Solution:
    def printMatrix(self, matrix):
        result = []
        while matrix:
            result += matrix.pop(0)
            if matrix:
                matrix = [[row[col] for row in matrix] for col in reversed(range(len(matrix[0])))]    # 逆时针旋转
        return result  
发表于 2018-08-10 17:31:46 回复(2)
class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {		
        vector<int> v;         
        if(matrix.size()==0||matrix[0].size()==0)return v;
        int a=0,x=matrix.size()-1,y=matrix[0].size()-1,i,j;        
        do{
        for(i=a,j=a;j<=y;j++) v.push_back(matrix[i][j]);
        for(i=a+1,j=y;i<=x;i++) v.push_back(matrix[i][j]);
        if(a!=x)for(i=x,j=y-1;j>=a;j--) v.push_back(matrix[i][j]);
        if(a!=y)for(i=x-1,j=a;i>=a+1;i--) v.push_back(matrix[i][j]);
        }while(++a<=--x&&a<=--y);
        return v; 
    }
};

发表于 2015-08-07 17:05:39 回复(3)
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
       ArrayList<Integer> ls = new ArrayList<Integer>();
		int colStart = 0;
		int colEnd = matrix[0].length;

		int lineStart = 0;
		int lineEnd = matrix.length;
		int count = lineEnd * colEnd;
		if (matrix == null)
			return ls;
		while (count != 0) {
			for(int i = colStart;i<colEnd;i++){
				ls.add(matrix[lineStart][i]);
				count--;
			}
			lineStart++;
			if(count==0)
				break;
			for(int i = lineStart;i<lineEnd;i++){
				ls.add(matrix[i][colEnd-1]);
				count--;
			}
			colEnd--;
			if(count==0)
				break;
			for(int i = colEnd-1;i>=colStart;i--){
				ls.add(matrix[lineEnd-1][i]);
				count--;
			}
			lineEnd--;
			if(count==0)
				break;
			for(int i = lineEnd-1;i>=lineStart;i--){
				ls.add(matrix[i][colStart]);
				count--;
			}
			colStart++;
			if(count==0)
				break;
		}
		return ls;
    }
}

发表于 2016-06-30 17:20:49 回复(1)
//很惭愧,编译了多次才通过的代码。。
/*
    思想,用左上和右下的坐标定位出一次要旋转打印的数据,一次旋转打印结束后,往对角分别前进和后退一个单位。
    提交代码时,主要的问题出在没有控制好后两个for循环,需要加入条件判断,防止出现单行或者单列的情况。
 */
class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
		int row = matrix.size();
        int col = matrix[0].size();
        vector<int> res;
        
        // 输入的二维数组非法,返回空的数组
        if (row == 0 || col == 0)  return res;
        
        // 定义四个关键变量,表示左上和右下的打印范围
        int left = 0, top = 0, right = col - 1, bottom = row - 1;
        while (left <= right && top <= bottom)
        {
            // left to right
            for (int i = left; i <= right; ++i)  res.push_back(matrix[top][i]);
            // top to bottom
            for (int i = top + 1; i <= bottom; ++i)  res.push_back(matrix[i][right]);
            // right to left
            if (top != bottom)
            for (int i = right - 1; i >= left; --i)  res.push_back(matrix[bottom][i]);
            // bottom to top
            if (left != right)
            for (int i = bottom - 1; i > top; --i)  res.push_back(matrix[i][left]);
            left++,top++,right--,bottom--;
        }
        return res;
    }
};

编辑于 2015-08-29 23:32:18 回复(69)

将最外层的四个边看成一个环,每成功'削'一个环,就接着削内层的环,直到削环失败

每次削环,按照上、右、下、左的顺序依次削边,每削一次边,检查一下环的完整性,若环不完整了,便认为是消环失败,返回false并退出

class Solution {
public:
    vector<int> *out;
    int top, bottom, left, right;
    bool printRing(vector<vector<int> > &m) {
        for (int i = left; i <= right; i++)
            out->push_back(m[top][i]);
        if (++top > bottom) return false;
        for (int i = top; i <= bottom; i++)
            out->push_back(m[i][right]);
        if (left > --right) return false;
        for (int i = right; i >= left; i--)
            out->push_back(m[bottom][i]);
        if (top > --bottom) return false;
        for (int i = bottom; i >= top; i--)
            out->push_back(m[i][left]);
        if (++left > right) return false;
        return true;
    }
    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector<int> ret;
        out = &ret;
        if (matrix.size()) {
            top = 0, bottom = matrix.size() - 1;
            left = 0, right = matrix[0].size() - 1;
            while (printRing(matrix));
        }
        return ret;
    }
};
发表于 2017-08-13 19:16:20 回复(0)

暴力 4个方向 右 下 左 上 依次循环

class Solution {
public:
    int dp[1000][1000];
    vector<int> printMatrix(vector<vector<int> > matrix) {
        int row = matrix.size(), col = matrix[0].size();
        int rs[] = {0, 1, 0, -1};
        int cs[] = {1, 0, -1, 0};
        memset(dp, 0, sizeof(dp));
        vector<int> ans;
        int dir = 0, r = 0, c = 0, step = row * col;
        while(step){
            step--; dp[r][c] = 1;
            ans.push_back(matrix[r][c]);
            if(r + rs[dir] >= row || r + rs[dir] < 0 || 
               c + cs[dir] >= col || c + cs[dir] < 0 ||
               dp[r + rs[dir]][c + cs[dir]]) dir = (dir + 1) % 4;
            r = r + rs[dir]; c = c + cs[dir];
        }
        return ans;
    }
};
发表于 2018-12-02 15:11:21 回复(0)
可以模拟魔方逆时针旋转的方法,一直做取出第一行的操作
例如 
1 2 3
4 5 6
7 8 9
输出并删除第一行后,再进行一次逆时针旋转,就变成:
6 9
5 8
4 7
继续重复上述操作即可。
Python代码如下

class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        result = []
        while(matrix):
            result+=matrix.pop(0)
            if not matrix or not matrix[0]:
                break
            matrix = self.turn(matrix)
        return result
    def turn(self,matrix):
        num_r = len(matrix)
        num_c = len(matrix[0])
        newmat = []
        for i in range(num_c):
            newmat2 = []
            for j in range(num_r):
                newmat2.append(matrix[j][i])
            newmat.append(newmat2)
        newmat.reverse()
        return newmat
编辑于 2016-08-16 20:09:28 回复(86)
还是原书的题解思路清晰:

我们注意到,左上角的坐标中行号和列号总是相同的,于是可以在矩阵中选取左上角为 (start, start) 的一圈作为我们分析的目标。经过分析,不论是5*5还是6*6的矩阵,左上角的坐标都符合start * 2 < matrix.length && start * 2 < matrix[start].length,所以可以以此为循环条件按圈打印矩阵。

接下来考虑如何打印一圈的数字。我们可以把打印一圈分为四步:第一步,从左到右打印一行;第二步,从上到下打印一列;第三步,从右到左打印一行;第四步,从下到上打印一列。需要注意的是,最后一圈有可能退化成只有一行、只有一列,甚至只有一个数字,因此打印这样的一圈就不需要四步了。

因此,我们要仔细分析打印每一步的前提条件。第一步总是需要的,因为打印一圈至少需要一步。如果只有一行,那就不用第二步了。也就是说第二步的前提条件是至少有两行。第三步的前提条件是至少有两行两列。第四步的前提条件是至少有三行两列。
import java.util.ArrayList;

public class Solution {

    public ArrayList<Integer> printMatrix(int[][] matrix) {
        if (matrix == null || matrix.length == 0) {
            return new ArrayList<>(0);
        }

        int start = 0;
        ArrayList<Integer> list = new ArrayList<>(matrix.length * matrix[0].length);

        // 使用乘2而不是除2, 可以避免奇偶数的差异
        while (start * 2 < matrix.length && start * 2 < matrix[start].length) {
            printMatrix(matrix, start, matrix.length - 2 * start, matrix[start].length - 2 * start, list);
            start++;
        }

        return list;
    }

    // 一圈的范围是[start, start] ~ [start+rows-1, start+cols-1]
    public void printMatrix(int[][] matrix, int start, int rows, int cols, ArrayList<Integer> list) {
        // 第一步, 肯定要执行
        for (int i = start, j = start; j < start + cols; j++) {
            list.add(matrix[i][j]);
        }

        // 第二步, 前提条件是圈内至少有两行
        if (rows >= 2) {
            for (int i = start + 1, j = start + cols - 1; i < start + rows; i++) {
                list.add(matrix[i][j]);
            }
        }

        // 第三步, 前提条件是圈内至少有两行两列
        if (rows >= 2 && cols >= 2) {
            for (int i = start + rows - 1, j = start + cols - 2; j >= start; j--) {
                list.add(matrix[i][j]);
            }
        }

        // 第四步, 前提条件是圈内至少有三行两列
        if (rows >= 3 && cols >= 2) {
            for (int i = start + rows - 2, j = start; i > start; i--) {
                list.add(matrix[i][j]);
            }
        }
    }
}


发表于 2021-08-17 14:19:24 回复(0)
import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        int n = matrix.length * matrix[0].length;
        ArrayList<Integer> ans = new ArrayList<>();
        int top = 0, bottom = matrix.length-1;
        int left = 0, right = matrix[0].length-1;
        while(top <= bottom && left <= right && ans.size() < n) {
            for(int i = left; i <= right && ans.size() < n; i++) {
                ans.add(matrix[top][i]);
            }
            for(int j = top+1; j < bottom && ans.size() < n; j++) {
                ans.add(matrix[j][right]);
            }
            for(int i = right; i >= left && ans.size() < n; i--) {
                ans.add(matrix[bottom][i]);
            }
            for(int j = bottom-1; j > top && ans.size() < n; j--) {
                ans.add(matrix[j][left]);
            }
            top++;
            left++;
            right--;
            bottom--;
        }
        return ans;
    }
}

发表于 2021-08-09 20:22:58 回复(0)
解题思路:逆时针旋转矩阵。转之前先保存首行数字,转的时候就把首行挤掉了
import java.util.ArrayList;
public class Solution {
    ArrayList<Integer> list = new ArrayList<>();
    //判断一下矩阵一边滚一边删干净了
    public ArrayList<Integer> printMatrix(int [][] matrix) {
       while(matrix.length>0 && matrix[0].length>0){
           matrix=delAndRoll(matrix);
       }
       return list;
    }
    
    //逆时针转90度 首行的处理是把首行数字加到list里 接着翻滚的时候就把首行挤掉了
    public int[][] delAndRoll(int[][] matrix) {
        int[][] temp = new int[matrix[0].length][matrix.length-1];
        for(int i=0;i<matrix.length;i++){
            for(int j=0;j<matrix[i].length;j++){
                if(i ==0 ){
                    list.add(matrix[i][j]);
                }else{
                    temp[matrix[i].length-j-1][i-1]=matrix[i][j];
                }
            }
        }
        return temp;
    }
     
}


发表于 2021-08-01 00:54:06 回复(1)

Java 记忆化搜索解法: 时间O(nm), 空间O(nm)

import java.util.ArrayList;
public class Solution {
    int n, m;
    boolean [][] f;
    int [][] pre;

    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> list = new ArrayList<>();
        if (matrix == null || matrix.length == 0) return list;
        n = matrix.length;
        m = matrix[0].length;

        f = new boolean[n + 5][m + 5];
        pre = new int[n + 5][m + 5];

        dfs(list, matrix, 0, 0);
        return list;
    }

    public void dfs(ArrayList<Integer> list, 
                    int [][] matrix, 
                    int x, int y) {
        if (f[x][y]) return;

        f[x][y] = true;
        list.add(matrix[x][y]);

        // 定义方向顺时针: 右->下->左->上
        int [] dx = {0, 1, 0, -1};
        int [] dy = {1, 0, -1, 0};

        // 尝试按原来的方向走
        int prev = pre[x][y];
        int a = x + dx[prev];
        int b = y + dy[prev];

        if (a >= 0 && a < n && b >= 0 && b < m) {
            // 可以走记录上一步走过的方向
            pre[a][b] = prev;
            dfs(list, matrix, a, b);
        }

        // 尝试别的走法
        for (int i = 0; i < 4; i++) {
            a = x + dx[i];
            b = y + dy[i];
            if (a >= 0 && a < n && b >= 0 && b < m) {
                // 可以走记录上一步走过的方向
                pre[a][b] = i;
                dfs(list, matrix, a, b);
            }      
        }
    }
}
发表于 2021-07-22 15:41:43 回复(0)
# -*- coding:utf-8 -*-
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here,可以模拟魔方逆时针旋转的方法,一直做取出第一行的操作
        result = []
        while matrix:
            result += matrix.pop(0)   # 取出第一行
            matrix = list(zip(*matrix)[::-1])
        return result

发表于 2021-03-17 08:55:28 回复(0)
我的思路是:设置一个方向数组,二维数组中元素每次移动后若逾界或碰到之前经过的节点,则更换方向。这个更换方向的次序是固定的(顺时针),当所有方向换一遍后依然无用,说明已到达最后节点,跳出循环即可。
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
        # write code here
        # 方向指针,每次移动时和4取余获得坐标增量
        directory = [(0,1),(1,0),(0,-1),(-1,0)]
        rows , cols=  len(matrix), len(matrix[0])
        path = [ [True]*cols for i in range(rows) ]
        seq = []
        # the start pos
        x,y = 0,0
        step, End = 0, False
        while True:
            seq.append(matrix[x][y])
            path[x][y] = False
            # let's move
            lsp = step
            nx, ny = x+ directory[step%4][0], y+ directory[step%4][1]
            while nx<0 or nx>=rows or ny<0 or ny>=cols or path[nx][ny]==False:
                step +=1
                if step - lsp ==4:
                    End = True
                    break
                nx, ny = x + directory[step % 4][0], y + directory[step % 4][1]
            # no way to move
            if End:
                break
            x, y = x+ directory[step%4][0], y+ directory[step%4][1]
        return seq


编辑于 2020-03-24 11:08:04 回复(0)