剑指offer-面试题 20:顺时针打印矩阵
来源:互联网 发布:安全数据库 编辑:程序博客网 时间:2024/06/06 00:30
# 面试题 20:顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
1. 思路
题目理解很简单。重要的是如何建模呢?容易想到,要做到从外往里打印,每当执行一次打印操作,必须将某个参数减1(我们先不用考虑具体的代码细节,只需要有这个思路即可)。对于具体的参数设计,我们在后面会有详细的解释。我们通过对题目分析,除了代码的实现,得出了两个比较重要的问题:
(1)代码如何终止?
(2)而对于极端情况(例如只有1行或者1列,或者只有一个数)该怎么做?
以下是我的详细思路:
1.1 建模
如图是一个二维矩阵的简单示意图。如果我们要顺时针打印一个矩阵,那么通常会分成四部分,先左右横,后上下竖,后右左横,最后下上竖,一个圈完成,之后类推。
实现顺时针转动的话,每部分完成后需要将某个参数减1(我们先不去关注具体是哪个参数),之后执行下一部分。
根据上述思路,我设置了四个轴,分别为:
up轴
,right轴
,down轴
和left轴
。 完成一圈的过程是:
(1)左右横,
up轴
向下移动一行; (2)上下竖,
right轴
向左移动一行; (3)右左横,
down轴
向上移动一行; (4)下上竖,
left轴
向右一行。 之后up轴从第二行开始(假设初始值是第1行)从左往右遍历,right轴从倒数第二列开始向下遍历(初始值最后一列),down轴从倒数第二行开始从右往左遍历(初始值为倒数第一行),left轴从第二列从下往上遍历(初始值为第一列)……
1.2 对结束条件的判断
那么如何判断执行到头了呢?我们可以从简单的情况开始思考:
(1)当二维数组只有一个数字时,行和列数均为1,那么只要打印出这个数就可以了。此时四个轴的值是什么呢?up,down,right和left均为1;
(2)当二维数组只有一行时,up = down ,left = 1,right = 列数(这里是列数)。
打印操作执行为打印这一行。用代码实现就是:
for(int i = 0; i < rowLen - 1; i++) { //列数不为1,逐个打印 System.out.println(a[0][i] + " "); //只有一行 }
(3)当二维数组只有一列时,left = right ,up = 1,down = 行数(这里是行数)。
打印操作执行为打印这一列,代码跟上面类似。
(4)更复杂的情形:
多行多列时,我们发现,打印的操作都是一个for循环,那么怎么确定到底是打印数组的哪条边呢?
我的想法是:打印有四个方向,每次从左往右横向打印完了,之后会打印从上往下。下次横向再打印时,方向肯定是从右往左;
每次从上往下纵向打印完了,之后横向从左往右打印。下次纵向再打印时,方向总是从下往上。
所以想法是设定两个方向判断变量rDir和cDir:其中rDir为行的方向变量,为1时从左往右,为0从右往左打印;cDir为列的方向变量,为1从上往下,为0从下往上打印。在代码中会对这两个变量进行赋值,用它们来判断打印的方向,下面是一个简单的情形:
int rDir = 1; // 行的方向变量,为1从左往右,为0从右往左打印 int cDir = 1; // 列的方向变量,为1从上往下,为0从下往上打印 …… if(rDir == 1) { printLR(a, left, right, up, down); up++; rDir = 0; }else { printRL(a, left, right, up, down); down--; rDir = 1; } …… if(up <= down) { if(cDir == 1) { printUD(a, left, right, up, down); right--; cDir = 0; }else { printDU(a, left, right, up, down); left++; cDir = 1; }
rDir默认为1,也就是从左到右打印,打印完后rDir赋值为0;为0时,代表从右到左打印,打印完后rDir变成0。
cDir默认为1,也就是从下到上打印,打印完后cDir赋值为0;为0时,代表从上到下打印,打印完后cDir变成0。
其中四个print方法是封装for循环的按方向打印的函数,具体实现会在后续代码中给出。
以上是我们对打印方向的确定和简单实现,那么回到我们最初提出的问题:
如何判断结束呢?其实就是判断up和down,left和right的大小。这部分比较简单,我们直接看代码:
2. 代码
package swordOffer;/**面试题 20:顺时针打印矩阵 * 题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。 * * @author Stephen Huge * @date 17/04/22 */public class Ex20PrintMatrixClockwisely { public static void main(String[] args) {// int[][] array = new int[3][0];// int[][] array = {{1,2,3,4,5}};// int[][] array = {{1},{2},{3},{4},{5}};// int[][] array = {{1,2,3},{2,3,4}}; int[][] array = {{1,2},{2,3},{3,4},{4,5},{5,6}}; // int[][] array = {{1,2,3},{2,3,4},{3,4,5}};// int[][] array={{1,2,3,4,5},{5,6,7,8,9},{9,10,11,12,13},{13,14,15,16,17},{17,18,19,20,21},{21,22,23,24,25}}; Ex20PrintMatrixClockwisely pmcw = new Ex20PrintMatrixClockwisely(); pmcw.printMatrixClociwisely(array); } public void printMatrixClociwisely(int[][] a) { if(a == null || a.length == 0 || (a.length > 0 && a[0].length == 0)) { System.out.println("Length error!"); return; } int up = 0; int down = a.length - 1; //每列的行数 int left = 0; int right = a[0].length - 1;//每行的列数 int rDir = 1; // 行的方向变量,为1从左往右,为0从右往左打印 int cDir = 1; // 列的方向变量,为1从上往下,为0从下往上打印 while(true) { if(left <= right) { if(rDir == 1) { printLR(a, left, right, up, down); up++; rDir = 0; }else { printRL(a, left, right, up, down); down--; rDir = 1; } }else { System.out.println("left > right"); return; } if(up <= down) { if(cDir == 1) { printUD(a, left, right, up, down); right--; cDir = 0; }else { printDU(a, left, right, up, down); left++; cDir = 1; } }else { System.out.println("up < down"); return; } } } private void printLR(int[][] a, int left, int right, int up, int down) { //从左到右打印 for(int i = left; i <= right; i++) { System.out.print(a[up][i] + " "); } System.out.print(". "); } private void printRL(int[][] a, int left, int right, int up, int down) { //从右到左打印 for(int i = right; i >= left; i--) { System.out.print(a[down][i] + " "); } System.out.print(". "); } private void printUD(int[][] a, int left, int right, int up, int down) { //从上到下打印 for(int i = up; i <= down; i++) { System.out.print(a[i][right] + " "); } System.out.print(". "); } private void printDU(int[][] a, int left, int right, int up, int down) { //从下到上打印 for(int l = down;l >= up; l--) { System.out.print(a[l][left] + " "); } System.out.print(". "); }}
运行结果:
1 2 . 3 4 5 6 . 5 . 4 3 2 .
在一个无限循环中,不断的判断up和down,left和right的大小。如果up > down
或者left > right
,循环结束,打印完成。
- 《剑指offer》面试题:顺时针打印矩阵
- 剑指offer面试题 顺时针打印矩阵
- 剑指offer面试题20顺时针打印矩阵
- [剑指offer][面试题20]顺时针打印矩阵
- 剑指offer 面试题20:顺时针打印矩阵
- 《剑指offer》面试题20顺时针打印矩阵
- 【剑指offer】面试题20:顺时针打印矩阵
- 剑指offer 面试题20 顺时针打印矩阵
- 剑指Offer:面试题20 顺时针打印矩阵
- 《剑指Offer》面试题20:顺时针打印矩阵
- 剑指offer 面试题20—顺时针打印矩阵
- 《剑指Offer》学习笔记--面试题20:顺时针打印矩阵
- 剑指offer--面试题20:顺时针打印矩阵--Java实现
- 【剑指Offer学习】【面试题20 : 顺时针打印矩阵】
- 剑指offer面试题20-顺时针打印矩阵
- 剑指offer-面试题20:顺时针打印矩阵
- 剑指offer之面试题20:顺时针打印矩阵
- 剑指offer之面试题20顺时针打印矩阵
- html和xml的区别
- (13.1.3.1)PMBOK之三:十大知识领域之整合管理
- React Native 嵌入到iOS原生应用
- 自动化用到的一些小技巧
- POJ 1679:The Unique MST(次小生成树)
- 剑指offer-面试题 20:顺时针打印矩阵
- C++作业5
- Java将远程服务器上的文件经过本地服务器中转后输出至前端
- poj 1236 Network of Schools
- Emmet(ZenCoding)语法(一)
- git的基础使用
- es6中"类"--class的方式创建对象和es5中正常用法比较
- [硬件]树莓派2代无显示器安装系统(固定IP+VNC开机自启动)
- 纯原生js 贪吃蛇(锻炼你逻辑思维)