[编程题]顺时针打印矩阵

# 1537个回答

import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int[][] matrix) {
ArrayList list = new ArrayList();
int firstRow = 0;
int lastRow = matrix.length - 1;
int firstColumn = 0;
int lastColumn = matrix[firstColumn].length - 1;
if (firstRow == lastRow && firstColumn == lastColumn) {
return list;
}
while ((firstRow <= lastRow || firstColumn <= lastColumn) && firstRow >= 0 && lastRow >= 0 && firstColumn >= 0
&& lastColumn >= 0) {

if ((lastRow - firstRow) == 0) {
print(list, matrix, firstRow, lastRow, firstColumn++, lastColumn--);
break;
} else if ((lastColumn - firstColumn) == 0) {
print(list, matrix, firstRow++, lastRow--, firstColumn, lastColumn);
break;
} else {
print(list, matrix, firstRow++, lastRow--, firstColumn++, lastColumn--);
}

}
return list;
}

public void print(ArrayList<Integer> list, int[][] matrix, int firstRow, int lastRow, int firstColumn,
int lastColumn) {
//从第一列开头扫描到结尾
if(firstRow<=lastRow) {
for (int i = firstColumn; i <= lastColumn; i++) {
}
}
//从最后一列第二行到最尾行
if (firstColumn <= lastColumn) {
for (int i = firstRow + 1; i <= lastRow; i++) {
}
}

//
if(firstRow<lastRow) {
for (int i = lastColumn - 1; i >= firstColumn; i--) {
}
}

if (firstColumn < lastColumn) {
for (int i = lastRow - 1; i >= firstRow + 1; i--) {
}
}

}
}

```/*解题思路：顺时针打印就是按圈数循环打印，一圈包含两行或者两列，在打印的时候会出现某一圈中只包含一行，要判断从左向右打印和从右向左打印的时候是否会出现重复打印，同样只包含一列时，要判断从上向下打印和从下向上打印的时候是否会出现重复打印的情况*/
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;
}
};

```

```//很惭愧，编译了多次才通过的代码。。
/*
思想，用左上和右下的坐标定位出一次要旋转打印的数据，一次旋转打印结束后，往对角分别前进和后退一个单位。
提交代码时，主要的问题出在没有控制好后两个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;
}
};```

# python solution:

``````
class Solution:

def printMatrix(self, matrix):
res = []
while matrix:
res += matrix.pop(0)
if matrix and matrix[0]:
for row in matrix:
res.append(row.pop())
if matrix:
res += matrix.pop()[::-1]
if matrix and matrix[0]:
for row in matrix[::-1]:
res.append(row.pop(0))
return res
``````

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```

``````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++){
}
}
else if(tC==dC){  再判断是否只是一竖列 如果是 打印该横行的列（通常用于内圈
for(int i=tR;i<=dR;i++){
}
}
else {
int curC=tC;用2个变量储存 用于判断当前位置
int curR=tR;
while(curC!=dC){      当前位置未到达当前行的最右列 --》往右去
curC++;
}
while(curR!=dR){      当前位置未到达当前列的最底行 --》往下去
curR++;
}
while(curC!=tC){      当前位置未到达当前行的最左列 --》往左去
curC--;
}
while(curR!=tR){      当前位置未到达当前列的最顶行 --》往上去
curR--;
}
}
}
}
``````

```//主体循环部分才5行。其实是有规律可循的。将每一层的四个边角搞清楚就可以打印出来了

import java.util.ArrayList;
public class Solution {
public ArrayList<Integer> printMatrix(int [][] array) {
ArrayList<Integer> result = new ArrayList<Integer> ();
if(array.length==0) return result;
int n = array.length,m = array[0].length;
if(m==0) return result;
int layers = (Math.min(n,m)-1)/2+1;//这个是层数
for(int i=0;i<layers;i++){
}
return result;
}
}
```

```class Solution {
public:
vector<int> printMatrix(vector<vector<int> > matrix) {
vector<int> ret;
if(matrix.empty())return ret;

int x,y,cnt=matrix[0].size()*matrix.size();
int rEdge=matrix[0].size()-1,dEdge=matrix.size()-1,lEdge=0,uEdge=0;
//bool first=true;
for(x=0,y=0;cnt>0;cnt--){
ret.push_back(matrix[x][y]);
//;2
//go  right
if(x==uEdge){if(y<rEdge)y++;
else if(y==rEdge){x++;}
continue;}

//down
if(y==rEdge){if(x<dEdge)x++;
else if(x==dEdge){y--;}
continue;}

//left
if(x==dEdge){if(y>lEdge)y--;
else if(y==lEdge){x--;}
continue;}

//up
if(y==lEdge){if(x>uEdge+1)x--;
else if( x==uEdge+1){y++;lEdge++;uEdge++;rEdge--;dEdge--;}
continue;}
//;3
}
return ret;
}```

```/*
* 采用旋转魔方的方式 一次取一行，然后旋转
*/
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++) {
}
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++)

// 从上往下打印，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++)

// 从右往左打印，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--)

// 从下往上打印，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--)
}
return al;
}```

-----------------------------------------------------------------------------------------
updata20171008

• 那也就是按照矩阵数据，一层层的画圈出来
• 那么这一画整个需求实现过程也就清晰了：究竟哪一部分是变量，哪一部分是循环量

• 很绝望的说，这个问题其实是难的，我前前后后想很久。。。具体思考是：
1. 为什么获取行列中最小的那个？尝试着在矩阵上画一个方形圈出来，只能以行/列中最小的为参考才能画出一个圈，否则以最大的为参考这个圈是画不出来的，因为最短边不够长
2. 圈数到底怎么算的？所谓的圈其实是一个方形，那么很显然只要有两行或者两列就得到一个圈，所以圈数=行or列/2。加一和减一是为了进行取舍。这里回头我会上图。

1. 第一个层循环的限定条件就是圈数
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;
}
};

```

```1.每次都是一个圈，所以定义四个变量限定每次循环的界限：
startRow,endRow,startCol,endCol；
2.分别把首行，末列，末行，首列的数据依次加入list；
3.注意不要重复加入某个点，每次都要限定界限。

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

int startRow = 0;
int endRow = row-1;
int startCol = 0;
int endCol = col-1;
while(startRow<=endRow&&startCol<=endCol){
//如果就剩下一行
if(startRow==endRow){
for(int i=startCol;i<=endCol;i++)
return list;
}
//如果就剩下一列
if(startCol==endCol){
for(int i=startRow;i<=endRow;i++)
return list;
}
//首行
for(int i=startCol;i<=endCol;i++)
//末列
for(int i=startRow+1;i<=endRow;i++)
//末行
for(int i=endCol-1;i>=startCol;i--)
//首列
for(int i=endRow-1;i>=startRow+1;i--)

startRow = startRow + 1;
endRow = endRow - 1;
startCol = startCol + 1;
endCol = endCol - 1;
}
return list;
}
```

```//借鉴的二楼的代码，对二楼的代码进行了部分判断条件的修改
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;
}
};```

1 2 3
4 5 6
7 8 9

4 5 6
7 8 9

6 9
5 8
4 7

```/**
* @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++)
// 从上到下打印一列
for(int j = start + 1; j < rows - start; j++)
// 从右到左打印一行
for(int m = columns - start - 2; m >= start && rows - start - 1 > start; m--)
// 从下到上打印一列
for(int n = rows - start - 2; n >= start + 1 && columns - start - 1 > start; n--)
}
}

```

```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;
}
};```

```#打印第一行，删除第一行，逆时针转动90度。重复以上步骤，直到矩阵为空。
class Solution:
def printMatrix(self, matrix):
# write code here
s=[]
while matrix:
s+=matrix[0]
del matrix[0]
matrix=zip(*matrix)[::-1]
return s```

```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;
}
};```

```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++){
count--;
}
lineStart++;
if(count==0)
break;
for(int i = lineStart;i<lineEnd;i++){
count--;
}
colEnd--;
if(count==0)
break;
for(int i = colEnd-1;i>=colStart;i--){
count--;
}
lineEnd--;
if(count==0)
break;
for(int i = lineEnd-1;i>=lineStart;i--){
count--;
}
colStart++;
if(count==0)
break;
}
return ls;
}
}```

``````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;
}
};
``````

```# -*- 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  ```

``````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;
}
};
``````

1537条回答 134559浏览

# 通过挑战的用户

• 2019-06-25 19:48:27
• 2019-06-25 19:47:19
• 2019-06-25 19:46:07
• 2019-06-25 19:45:19
• 2019-06-25 19:31:52

# 相关试题

• 扫描二维码，关注牛客网

• 下载牛客APP，随时随地刷题