题目出自《剑指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
分别代表左上,右下两个顶点的横纵坐标。
如下图:(瞧瞧瞧瞧,我又来画画了。)
好了,现在你大概知道是怎么个情况了,
使用递归来剥开你的心。
递归传参如下:
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<Integer> list = new ArrayList<>();
public ArrayList<Integer> 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)
第二种是:横条条(lft < rgt,btm = top)
第三种是: 正常大矩阵
一个正常的方形矩阵,每次递归总是执行第三种情况。
而一个长比宽大的矩阵,剥到最后就剩一个横条条了。
而一个宽比长大的矩形,剥到最后就剩一个竖条条了。
所以针对这三种情况,我都讨论了。
一开始没讨论老是重复打印。
4. 运行
为了练习北邮研究生复试上机,上机4个算法题,可以用IDE
一开始我是在线写的。
结果提交三次没成功!!!
然后换成IDE,小邮邮规定用eclipse没有idea,真的用久了idea不想再碰eclipse。
笨拙的调试了一番,发现我上面提到的三种情况,(一开始我就一种正方形的情况,我以为加了终止条件就可以),因此我又重新分了一下。
最后是算5次罚时,尴尬
运行时间20ms多,自从开始刷剑指的题就被一群大佬血虐,排行榜上再也看不到名字了,不过现在的目标是为了机试,AC为主。
好嘞,这道题就到这里吧!