剑指offer 面试题20—顺时针打印矩阵
2015-04-29 19:25
471 查看
题目:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如:如果输入如下矩阵:
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。
基本思想:
通常当我们遇到一个复杂的问题的时候,我们可以用图形帮助我们思考。由于我们是以从外圈到内圈的顺序依次打印,我们在矩阵中标注一圈作为我们分析的目标。在下图中,我们设矩阵的宽度为columns,而其高度为rows。我们我们选取左上角坐标为(startX,
startY),右下角坐标为(endX, endY)的一个圈来分析。
![](http://img.blog.csdn.net/20150429193047230?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3R5dmhyZWFs/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
由于endX和endY可以根据startX、startY以及columns、rows来求得,因此此时我们只需要引入startX和startY两个变量。我们可以想象有一个循环,在每一次循环里我们从(startX,
startY)出发按照顺时针打印数字。
接着我们分析这个循环结束的条件。对一个5×5的矩阵而言,最后一圈只有一个数字,对应的坐标为(2, 2)。我们发现5 > 2 * 2。对一个6×6的矩阵而言,最后一圈有四个数字,对应的坐标仍然为(2,
2)。我们发现6 > 2 * 2依然成立。于是我们可以得出,让循环继续的条件是columns > startX * 2 && rows > startY * 2。
接下来我们分析如何按照顺时针的顺序打印一圈的数字。如同在图中标注的那样,我们可以分四步来打印:第一步是从左到右打印一行(上图中***区域),第二步是从上到下打印一列(上图中绿色区域),第三步从右到左打印一行(上图中蓝色区域),最后一步是从下到上打印一列(上图中紫色区域)。也就是我们把打印一圈数字这个问题,分解成四个子问题。
值得注意的是,最后一圈可能退化成只有一行、只有一列、甚至只有一个数字,因此打印这样的一圈就不需要四步了。
![](http://img.blog.csdn.net/20150429193207650?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3R5dmhyZWFs/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20150429193217307?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd3R5dmhyZWFs/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
例如:如果输入如下矩阵:
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。
基本思想:
通常当我们遇到一个复杂的问题的时候,我们可以用图形帮助我们思考。由于我们是以从外圈到内圈的顺序依次打印,我们在矩阵中标注一圈作为我们分析的目标。在下图中,我们设矩阵的宽度为columns,而其高度为rows。我们我们选取左上角坐标为(startX,
startY),右下角坐标为(endX, endY)的一个圈来分析。
由于endX和endY可以根据startX、startY以及columns、rows来求得,因此此时我们只需要引入startX和startY两个变量。我们可以想象有一个循环,在每一次循环里我们从(startX,
startY)出发按照顺时针打印数字。
接着我们分析这个循环结束的条件。对一个5×5的矩阵而言,最后一圈只有一个数字,对应的坐标为(2, 2)。我们发现5 > 2 * 2。对一个6×6的矩阵而言,最后一圈有四个数字,对应的坐标仍然为(2,
2)。我们发现6 > 2 * 2依然成立。于是我们可以得出,让循环继续的条件是columns > startX * 2 && rows > startY * 2。
接下来我们分析如何按照顺时针的顺序打印一圈的数字。如同在图中标注的那样,我们可以分四步来打印:第一步是从左到右打印一行(上图中***区域),第二步是从上到下打印一列(上图中绿色区域),第三步从右到左打印一行(上图中蓝色区域),最后一步是从下到上打印一列(上图中紫色区域)。也就是我们把打印一圈数字这个问题,分解成四个子问题。
值得注意的是,最后一圈可能退化成只有一行、只有一列、甚至只有一个数字,因此打印这样的一圈就不需要四步了。
#include <iostream> using namespace std; void PrintMatrixIncircle(int nArr[][4], int rows, int columns, int nStart) { int nEndX = columns - 1 -nStart; int nEndY = rows - 1 -nStart; //从左到右打印一行 for (int i=nStart; i<=nEndX; i++) { cout << nArr[nStart][i] << " "; } //从上到下打印一列 if (nEndY > nStart) { for (int j=nStart+1; j<=nEndY; j++) { cout << nArr[j][nEndX] << " "; } } //从右到左打印一行 if (nEndY > nStart && nEndX > nStart) { for (int t=nEndX-1; t>=nStart; t--) { cout << nArr[nEndY][t] << " "; } } //从下到上打印一列 if (nEndY -1 > nStart && nEndX > nStart) { for (int n=nEndY-1; n>=nStart+1; n--) { cout << nArr [nStart] << " "; } } } //顺时针打印矩阵,行数为rows,列数为columns void PrintMatrixClockWisely(int nArr[][4], int rows, int columns) { if (nArr == NULL || rows <= 0 || columns <= 0) return ; int nStart = 0; while (rows>(nStart*2) && columns>(nStart*2)) { PrintMatrixIncircle(nArr, rows, columns, nStart); nStart++; } } int main() { int nMatrix[4][4] = { {1,2,3,4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}; PrintMatrixClockWisely(nMatrix, 4, 4); cout << endl; return 0; }
相关文章推荐
- 剑指Offer----面试题20:顺时针打印矩阵
- 剑指Offer面试题20(Java版):顺时针打印矩阵
- 剑指offer--面试题20:顺时针打印矩阵--Java实现
- 剑指offer——面试题20:顺时针打印矩阵
- 剑指Offer面试题20顺时针打印矩阵,面试题21包含min函数的栈
- 剑指offer之面试题20:顺时针打印矩阵
- 剑指 offer面试题20 顺时针打印矩阵
- 剑指offer-面试题20:顺时针打印矩阵
- 剑指offer——面试题20:顺时针打印矩阵
- 【剑指offer】面试题20:顺时针打印矩阵
- 剑指offer面试题20 顺时针打印矩阵
- 剑指Offer之面试题20:顺时针打印矩阵
- 剑指offer-面试题20.顺时针打印矩阵
- 剑指offer_面试题20_顺时针打印矩阵(思路在一步步分解之中)
- 剑指offer-面试题20.顺时针打印矩阵
- 【面试题】剑指offer20--顺时针打印一个矩阵的数字
- 【剑指Offer学习】【面试题20 : 顺时针打印矩阵】
- 剑指offer 面试题20 顺时针打印矩阵
- [剑指offer][面试题20]顺时针打印矩阵
- 剑指offer之面试题20:顺时针打印矩阵