概述
剑指offer中的题目,输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,如:
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
通过画图可以知道,其实就是若干个圈,依次打印出每个圈。而每个圈都要按照顺时针的顺序打印,即4个循环,先从左到右,再从上到下,再从右到左,再从下到上,只是最后一圈,可能只剩下其中的1步或3步。那么问题的关键就是找出一个矩阵可以转换成多少圈。注意要考虑行列不等的矩阵,要从最小的行数或列数下手,推算一个矩阵的圈数。这需要比较好的数学功底,先看4*4以及6*6这种情况,行列数相等,圈数为行数/2或列数/2,因此,可以初步猜测圈数是行列数最小的那个除以2,再考虑特殊情况,假如只有1行3列,那么圈数为1,此时1<3,圈数如果按1/2的方式算,为0,不对,需要+1,即min{行数,列数}/2+1,再带到4*4的情况,又多了一圈,因此需要改变min中情形,由程序中/的特性,将min{行数,列数}-1后/2,带入上述2种情形,均满足,再检验一下2*3,2*4,3*4等情形均符合,因此,最终圈数公式为[min{行数,列数}-1]/2。推算出这个公式后,剩下工作就是按照每圈进行4个方向的遍历即可。代码如下:
public ArrayList<Integer> printMatrix(int[][] array) {
ArrayList<Integer> result = new ArrayList<>();
if (array.length == 0) {
return result;
}
int n = array.length; //行数
int m = array[0].length; //列数
if (m == 0) {
return result;
}
int layers = (Math.min(n, m) - 1) / 2 + 1; //求圈数
for (int i = 0; i < layers; i++) {
//打印每周
for (int k = i; k < m - i; k++) {
result.add(array[i][k]); //从左到右
}
for (int j = i + 1; j < n - i; j++) {
result.add(array[j][m - i - 1]); //从右上到右下
}
for (int k = m - i - 2; (k >= i) && (n - i - 1 != i); k--) {
result.add(array[n - i - 1][k]); //从右到左
}
for (int j = n - i - 2; (j > i) && (m - i - 1 != j); j--) {
result.add(array[j][i]); //从左下到左上
}
}
return result;
}
剑指offer中提供的思路其实要更容易一些,首先分析循环结束的条件,打印第一圈左上角坐标为(0,0),第二圈左上角坐标为(1,1),以此类推每次循环的行列起始坐标都是相同的(start,start)。因此可以分析出循环继续的条件是columns > startX*2并且rows > startY*2。有了循环继续的条件后,我们要分析每次循环那4步的前提条件。第一步肯定是必定会经过的,因为打印一圈至少有一步。第二步的前提是终止行号大于起始行号,第三步的前提是终止行号大于起始行号,终止列号大于起始列号,因为圈内至少有2行2列,第四步的前提条件是终止行号比起始行号至少大2,终止列号大于起始行号,即至少有3行2列。代码如下:
public ArrayList<Integer> printMatrix(int[][] matrix) {
ArrayList<Integer> list = new ArrayList<>();
if (matrix == null)
return list;
int start = 0;
while (matrix[0].length > start * 2 && matrix.length > start * 2) {
printOneCircle(matrix, start, list);
start++;
}
return list;
}
private void printMatrixInCircle(int[][] matrix, int start, ArrayList<Integer> list) {
int endX = matrix[0].length - 1 - start; //列
int endY = matrix.length - 1 - start; //行
//从左往右
for (int i = start; i <= endX; i++) {
list.add(matrix[start][i]);
}
//从上往下
if (start < endY) {
for (int i = start + 1; i <= endY; i++) {
list.add(matrix[i][endY]);
}
}
// 从右往左(判断是否会重复打印)
if (start < endX && start < endY) {
for (int i = endX - 1; i >= start; i--)
list.add(matrix[endY][i]);
}
// 从下往上(判断是否会重复打印)
if (start < endX && start < endY - 1) {
for (int i = endY - 1; i >= start + 1; i--)
list.add(matrix[i][start]);
}
}
最后
以上就是彪壮大碗为你收集整理的顺时针打印矩阵java的全部内容,希望文章能够帮你解决顺时针打印矩阵java所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复