一、题目

  输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 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.

注释:输入的矩阵

          1     2     3    4

             5     6     7    8

              9   10   11   12

             13  14   15   16

二、思路

问题的本质其实就是打印一个方形。每一个方形代表矩阵的每一层。
但是,打印一个方形,我们必须要知道它的两个对角顶点的位置。有了对角顶点的位置,打印一个方形并不困难了。
注意:对于一个矩阵,它的长宽可能会不一样,所以,我们需要判断处理。
两个对角顶点的位置分别为左上角和右下角我们假设矩阵行数是rows,列数是culmns。
则左上角的位置行标和列标总是相同的,我们取左上角为(start,atart),则右下角为(rows-1,clumns-1)。
问题的关键在于,怎么确定循环终止条件:
对一个5*5的矩阵而言,最后一圈只有一个数字,对应的坐标为(2,2)。我们发现5>2*2.对于一个6*6的矩阵而言,最后一圈有4个数字,其左上角的坐标仍然为(2,2)。我们发现6>2*2依然成立。于是我们可以得出继续循环的条件是columns>2*start并且rows>2*start.

三、代码

形式1:顺时针遍历 的矩阵存入ArrayList

  1. import java.util.ArrayList;
  2.  
  3. public class PrintMatrix {
  4.  
  5. ArrayList<Integer> arrayList = new ArrayList<Integer>(); //存储顺时针打印的矩阵
  6.  
  7. //循环打印矩阵
  8. public ArrayList<Integer> printMatrix(int[][] matrix) {
  9. int clumns = matrix[0].length;//矩阵的列数
  10. int rows = matrix.length;//矩阵的行数
  11. if (matrix == null)//如果为空,返回null
  12. return null;
  13.  
  14. int start = 0;//定义矩阵初始元数的序号
  15.  
  16. while (clumns > 2 * start && rows > 2 * start) { //对一个5*5的矩阵而言,最后一圈只有一个数字,对应的坐标为(2,2)。我们发现5>2*2.对于一个6*6的矩阵而言,最后一圈有4个数字,其左上角的坐标仍然为(2,2)。我们发现6>2*2依然成立。于是我们可以得出继续循环的条件是columns>2*start并且rows>2*start.
  17. printMatrixInCircle(matrix, clumns, rows, start);//调用打印一圈的方法
  18. start++;
  19. }
  20. return arrayList;
  21. }
  22.  
  23. //打印一圈
  24. private void printMatrixInCircle(int[][] matrix, int clumns, int rows, int start) {
  25. int endX = clumns - 1 - start;
  26. int endY = rows - 1 - start;
  27. for (int i = start; i <= endX; ++i) {
  28. int n = matrix[start][i];
  29. arrayList.add(n);
  30. }
  31. //从上到下打印一列
  32. if (start < endY) {
  33. for (int j = start + 1; j <= endY; ++j) {
  34. int n = matrix[j][endX];
  35. arrayList.add(n);
  36. }
  37. }
  38. System.out.println();
  39. //从右到左打印一行
  40. if (start < endY && start < endX) {
  41. for (int k = endX - 1; k >= start; k--) {
  42. int n = matrix[endY][k];
  43. arrayList.add(n);
  44. }
  45. }
  46. //从下到上打印一列
  47. if (start < endX && start < endY - 1) {
  48. for (int l = endY - 1; l > start; l--) {
  49. int n = matrix[l][start];
  50. arrayList.add(n);
  51. }
  52. }
  53. }
  54. }

形式2:直接顺时针打印矩阵

  1. public class PrintMatrix {
  2. public static void main(String[] args) {
  3. int[][] num = new int[][]{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}, {16, 17, 18, 19, 20}, {21, 22, 23, 24, 25}};
  4. System.out.println("顺时针打印5x5的矩阵");
  5. printMatrixClockwisely(num, 5, 5);
  6. int[][] num2 = new int[][]{{1, 2, 3, 4, 5}};
  7. System.out.println("顺时针打印1x5的矩阵");
  8. printMatrixClockwisely(num2, 5, 1);
  9. int[][] num3 = new int[][]{{1}, {2}, {3}, {4}, {5}};
  10. System.out.println("顺时针打印5x1的矩阵");
  11. printMatrixClockwisely(num3, 1, 5);
  12. }
  13.  
  14. //循环打印矩阵
  15. public static void printMatrixClockwisely(int[][] numbers, int clumns, int rows) {
  16. if (numbers == null || clumns <= 0 || rows <= 0)
  17. return;
  18. int start = 0;
  19. //对一个5*5的矩阵而言,最后一圈只有一个数字,对应的坐标为(2,2)。我们发现5>2*2.对于一个6*6的矩阵而言,最后一圈有4个数字,其左上角的坐标仍然为(2,2)。我们发现6>2*2依然成立。于是我们可以得出继续循环的条件是columns>2*start并且rows>2*start.
  20. while (clumns > 2 * start && rows > 2 * start) {
  21. printMatrixInCircle(numbers, clumns, rows, start);
  22. start++;
  23. }
  24. }
  25.  
  26. //打印一圈
  27. private static void printMatrixInCircle(int[][] numbers, int clumns, int rows, int start) {
  28. int endX = clumns - 1 - start;
  29. int endY = rows - 1 - start;
  30. //从左到右打印一行
  31. for (int i = start; i <= endX; ++i) {
  32. int n = numbers[start][i];
  33. System.out.print(n + " ");
  34. }
  35. System.out.println();
  36. //从上到下打印一列
  37. if (start < endY) {
  38. for (int j = start + 1; j <= endY; ++j) {
  39. int n = numbers[j][endX];
  40. System.out.print(n + " ");
  41. }
  42. }
  43. System.out.println();
  44. //从右到左打印一行
  45. if (start < endY && start < endX) {
  46. for (int k = endX - 1; k >= start; k--) {
  47. int n = numbers[endY][k];
  48. System.out.print(n + " ");
  49. }
  50. }
  51. System.out.println();
  52. //从下到上打印一列
  53. if (start < endX && start < endY - 1) {
  54. for (int l = endY - 1; l > start; l--) {
  55. int n = numbers[l][start];
  56. System.out.print(n + " ");
  57. }
  58. }
  59. System.out.println();
  60. }
  61. }

-------------------------------------------------------------------------------------------------------

参考链接:

1、https://www.nowcoder.com/questionTerminal/9b4c81a02cd34f76be2659fa0d54342a

2、http://blog.163.com/wzz_vie/blog/static/25164906720173106320185/

剑指offer十九之顺时针打印矩阵的更多相关文章

  1. 剑指Offer:面试题20——顺时针打印矩阵(java实现)

    题目描述: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数 字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1, ...

  2. 剑指 offer面试题20 顺时针打印矩阵

    [题目描述] 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1, ...

  3. 剑指offer(19)顺时针打印矩阵

    题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2, ...

  4. 【剑指Offer】19、顺时针打印矩阵

      题目描述:   输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依 ...

  5. 【剑指offer】题目20 顺时针打印矩阵

    输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1   2   3  4 5   6   7  8 9  10 11 12 13 14 15 16 则依次打印出 ...

  6. 牛客网剑指offer第19题——顺时针打印矩阵

    这个题看似很简单: 题目: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 ...

  7. 剑指Offer(十九)——顺时针打印矩阵

    题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字. 例如,如果输入如下4 X 4矩阵: 1   2    3     4 5   6    7     8 9   10  11  ...

  8. 《剑指offer》从尾到头打印链表

    本题来自<剑指offer> 从尾到头打印链表 题目: 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. 思路: 方案一:首先遍历到尾部,然后从尾部进行到头值进行操作,后进先 ...

  9. 菜鸟刷题路:剑指 Offer 06. 从尾到头打印链表

    剑指 Offer 06. 从尾到头打印链表 class Solution { public int[] reversePrint(ListNode head) { Stack<Integer&g ...

随机推荐

  1. IntelliJ IDEA 2017版 编译器使用学习笔记(十) (图文详尽版);IDE快捷键使用;IDE关联一切

    关联一切 一.与spring关联      通过图标跳转相关联的类 设置关联:进入project structure ===>facets =>选加号,===>选spring,默认添 ...

  2. JS中的计时器事件

    JS可以实现很多java代码不易完成的功能.这里学习一些js中的计时器事件. JavaScript 一个设定的时间间隔之后来执行代码,称之为计时事件. 主要通过两个方法来实现: 1.setInterv ...

  3. matlab生成滤波器系数组

    用MATLAB生成的滤波器系数是可以控制增益的,一般归一化的目的是控制增益为1.滤波器的阶数由数据速率,过渡带宽.通带波纹和阴带波纹来决定, 在下图中FS,Apass,Astop固定之后,只要Fpas ...

  4. silverlight 父窗体传值给ChildWindow

    在网上找了许多列子,有的没有看懂,有的太麻烦. 现在有两种方法又简单又实用的,分享给大家! 第一种:使用构造函数传值 1.子页面新建一个构造函数 public ChildWindowTest(stri ...

  5. DS8800后端的光纤通道交换式互连方式

    DS8800 使用SAS 硬盘.使用了FC 到SAS 转换,光纤通道交换技术被用于DS8800 后端. FC 技术是普遍用于在一个光纤通道仲裁环路(Fibre Channel Arbitrated L ...

  6. 使用Golang+Mongodb打造你的第一个站点

    很多人推荐MEAN来开发站点.MEAN就是M:mongodb,E:expressjs.A:angular最后的N:nodejs. 但是如果你亲身的体会到了js的嵌套回调的话你就会想换换别的办法了.虽然 ...

  7. Android-WebView加载网页(new WebView(this)方式)

    之前的博客,都是 findViewById(R.id.webview);,来得到WebView, 此博客使用 new WebView(this)方式; AndroidManifest.xml中配置网络 ...

  8. SharePoint 列表中增加列编辑功能菜单

    需求描述 在企业的部署中,经常将SharePoint和TFS集成在一起,两个系统之间相互读取数据,展现开发进度.在TFS 2018之前版本中,由于TFS的门户定制功能有限,用户比较喜欢使用ShareP ...

  9. JS学习笔记3_函数表达式

    1.函数表达式与函数声明的区别 函数声明有“提升”(hoisting)的特性,而函数表达式没有.也就是说,函数声明会在加载代码时被预先加载到context中,而函数表达式只有在执行表达式语句时才会被加 ...

  10. C# DataGridView中单元格Cell改变事件

    DataGridView控件中的各种事件都无法直接响应Cell中内容的变化,包括KeyPress等事件,可以采用下面方法 private void dataGridViewBarcode_Editin ...