2019-03-15 顺时针打印矩阵

题目出自《剑指offer》,整理自牛客网
https://www.nowcoder.com/practice/9b4c81a02cd34f76be2659fa0d54342a

1. 问题

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

2.分析

首先打印想到的打印矩阵是一个螺旋型的操作。顺时针,一层一层。
然后马上映入脑海的是下面这几个词:

递归
分治
一层一层剥开你的心

手头没有笔,我就直接写到了注释里面。
然后继续思考,采用递归的方法需要注意,这可能不是一个方形矩阵,虽然说题目给了一个4*4,但是你不知道能出现什么情况。
既然不是方形,我们不能用对角线来确定螺旋点。
那用什么?
这就是一个数学问题了。

知道两个顶点可以确定一个矩形,但是这两个顶点必须是对角线的两端。

那么怎么确定这两个顶点?
这简单啊,问问笛卡尔同学。

笛卡尔说知道一个x,一个y就可以在我的坐标系上找到一确定点。

我说知道了,于是我搞了四个参数
lft,top
rgt,btm
分别代表左上,右下两个顶点的横纵坐标。

如下图:(瞧瞧瞧瞧,我又来画画了。)

2019-03-15 顺时针打印矩阵_第1张图片
image.png

好了,现在你大概知道是怎么个情况了,
使用递归来剥开你的心。

递归传参如下:

void getPrint(int[][] matrix,int lft,int top,int rgt,int btm)

使用后面四个参数就可以限定matrix的范围。

那如何结束呢?

 if(lft > rgt || top > btm){
          return;
      }

剥过头了就结束。

那如何剥?

 getPrint(matrix,lft + 1,top + 1,rgt - 1,btm - 1);

这个你画一个大大的矩阵看看就知道了,lft向右,rgt向左,top向下,btm向上。

于是我激动的写起来代码……
然额,产生了各种越界错误,重复打印balabala……

这个时候就要好好检查一下自己写的边界了,而且想象一下螺旋打印不是简单的打印四边,有些重叠点不要打印。

3. 代码

import java.util.ArrayList;
public class Solution {
    ArrayList list = new ArrayList<>();
    
    public ArrayList printMatrix(int [][] matrix) {
       //思路,递归,分治,一层一层剥开你的心
       getPrint(matrix,0,0,matrix[0].length - 1,matrix.length - 1); 
        
       return list; 
    }
    
    public void getPrint(int[][] matrix,int lft,int top,int rgt,int btm){
   
      if(lft > rgt || top > btm){
          return;
      }
      
      if(lft == rgt && btm > top){
         for(int t = top;t <= btm;t++){
             list.add(matrix[t][lft]);
         }
      }else if(btm == top && lft < rgt){
         for(int w = lft;w <= rgt;w++){
             list.add(matrix[top][w]);
         }
      }else{
          for(int i = lft; i <= rgt;i++){
              list.add(matrix[top][i]); //横1
          }
          
          for(int j = top + 1; j <= btm;j++){
              list.add(matrix[j][rgt]); //竖1
          } 
          
           for(int k = rgt - 1; k >= lft;k--){
              list.add(matrix[btm][k]); //横2
           }
          
           for(int l = btm - 1; l >= top + 1;l--){
              list.add(matrix[l][lft]); //竖2
           } 
      }
 
       getPrint(matrix,lft + 1,top + 1,rgt - 1,btm - 1);
    }
}

我们来看递归体,里面除了终止条件,我还写了其他三种选择。
第一种是:竖条条(lft = rgt ,btm > top)


2019-03-15 顺时针打印矩阵_第2张图片
image.png

第二种是:横条条(lft < rgt,btm = top)


2019-03-15 顺时针打印矩阵_第3张图片
image.png

第三种是: 正常大矩阵
一个正常的方形矩阵,每次递归总是执行第三种情况。
而一个长比宽大的矩阵,剥到最后就剩一个横条条了。
而一个宽比长大的矩形,剥到最后就剩一个竖条条了。

所以针对这三种情况,我都讨论了。
一开始没讨论老是重复打印。

4. 运行

为了练习北邮研究生复试上机,上机4个算法题,可以用IDE
一开始我是在线写的。
结果提交三次没成功!!!

然后换成IDE,小邮邮规定用eclipse没有idea,真的用久了idea不想再碰eclipse。

笨拙的调试了一番,发现我上面提到的三种情况,(一开始我就一种正方形的情况,我以为加了终止条件就可以),因此我又重新分了一下。

最后是算5次罚时,尴尬

运行时间20ms多,自从开始刷剑指的题就被一群大佬血虐,排行榜上再也看不到名字了,不过现在的目标是为了机试,AC为主。

好嘞,这道题就到这里吧!

你可能感兴趣的:(2019-03-15 顺时针打印矩阵)