面试题(剑指offer):顺时针打印矩阵

题目描述

输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 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,0),第二圈的左上角为(1,1),……,第n圈的左上角为(n-1,n-1);

接下来,多分析矩阵,找出一些规律。


对于4x4矩阵,它的最后一圈的左上角为(1,1),可以发现:4 > 1*1;

对于5x5矩阵,它的最后一圈(只有一个数字),左上角为(2,2),可以发现:5 > 2*2;

对于6x6矩阵,它的最后一圈的左上角为(2,2),可以发现:6 > 2*2;

……

不难得出,对于n*n矩阵,打印的最后一圈的左上角若为(x,x),则:n > x*x。

所以现在得出了按圈数循环的结束条件:行数或者列数必须大于当前左上角坐标之积。

所以目前需要知道如何打印单圈?

打印单圈分四步:

1.从左往右

2.从上到下

3.从右往左

4.从下到上


但是当打印最后一圈时,并不是一定都走这四步的。

思考一下:

    如果最后一圈只有一行了,那就只需要走第一步,不需要走第二步了;

    要走第二步,至少需要列数为二;

    而要走第三部步,则至少需要行数为二;

    要走第四步,则至少需要三行两列。

所以第一步一定要走。



接下来是代码,start是表示第几圈。

//打印单圈
void PrintMatrixInCircle(vector<vector<int> > matrix, vector<int>& ret, int start)
{
	int endx = matrix[0].size() - 1 - start;
	int endy = matrix.size() - 1 - start;

	//从左到右
		for (size_t i = start; i <= endx; i++)
			ret.push_back(matrix[start][i]);

	//从上到下
	if (endy > start)
	{
		for (size_t i = start + 1; i <= endy; i++)
			ret.push_back(matrix[i][endx]);
	}

	//从右到左打一行
	if (endx > start && endy > start)
	{
		for (int i = endx - 1; i >= start; i--)
		{
			ret.push_back(matrix[endx][i]);
		}
	}
	
	//从下到上打印一列
	if (endy - start > 1 && endx > start)
	{
		for (int i = endy - 1; i > start; i--)
		{
			ret.push_back(matrix[i][start]);
		}
	}
}


vector<int> printMatrix(vector<vector<int> > matrix)
{
	vector<int> ret;
	int start = 0;
	int row = matrix[0].size();//行
	int col = matrix.size();//列
	
	//n*n矩阵,最后一圈左上角为(a,a),通过规律,n > a*a,这就是循环继续条件
	while (row > start * 2 && col > start * 2)
	{
		PrintMatrixInCircle(matrix, ret, start);
		++start;
	}
	return ret;
}

 

猜你喜欢

转载自blog.csdn.net/han8040laixin/article/details/80513398