前言
当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~
在此感谢左大神让我对算法有了新的感悟认识!
问题介绍
原问题
给定二维矩阵arr,斜向之字形打印矩阵,
如arr:
[
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
]
\begin{bmatrix} 1 & 2 & 3 & 4 \\ 5 & 6 & 7 & 8 \\ 9 & 10 & 11 & 12 \\ 13 & 14 & 15 & 16 \end{bmatrix}
15913261014371115481216
打印结果:
1,2,5,9,6,3,4,7,10,13,14,11,8,12,15,16
解决方案
原问题:
问题分解为两个步骤:
1、从1开始斜方向执行循环
2、给定一个起点,和方向,从该起点开始一直打印到边界(i或者j到边界为止)
步骤1需要注意接下来的走向,我们发现向上的终点如果是j+1出界,则往下走,如果i-1出界,则往右走
如果是向下走的终点,则如果i+1出界,往右走,j-1出界往下走
代码编写
java语言版本
原问题:
/**
* 二轮测试:之字形打印矩阵
* @param arr
*/
public static void printMartrixZCp1(int[][] arr) {
if (arr == null || arr.length == 0) {
return;
}
int len1 = arr.length;
int len2 = arr[0].length;
// 循环次数
int count = len1 + len2 - 1;
int index = 0;
// 方向:true为向上
boolean forward = true;
// 初始化起点,start[0]纵坐标i,start[1]横坐标j
int[] start = new int[]{0,0};
while (index < count) {
process(arr, start, forward);
// 计算下一个起点
if (forward) {
if (start[1] + 1 >= len2) {
start[0] = start[0]+1;
}else if (start[0] - 1 < 0) {
start[1] = start[1] + 1;
}
}else {
// 向下
if (start[0] + 1 >= len1) {
start[1] = start[1]+1;
}else if (start[1] - 1 < 0) {
start[0] = start[0] + 1;
}
}
// 转换方向
forward = !forward;
index ++;
}
}
/**
* 从arr的ij开始,按照forward方向打印到边界
* @param arr
* @param forward
*/
private static void process(int[][] arr, int[] start, boolean forward) {
int len1 = arr.length;
int len2 = arr[0].length;
while (start[0] < len1 && start[0] >=0 && start[1] >= 0 && start[1] < len2) {
System.out.print(arr[start[0]][start[1]] + " ");
if (forward) {
if (start[0] - 1 < 0 || start[1] + 1 >= len2) {
// 越界退出
break;
}
start[0] = start[0] - 1;
start[1] = start[1] + 1;
}else {
if (start[0] + 1 >= len1 || start[1] - 1 < 0) {
// 越界退出
break;
}
start[0] = start[0] + 1;
start[1] = start[1] - 1;
}
}
}
public static void main(String[] args) {
printMartrixZCp1(new int[][] {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
});
}
c语言版本
正在学习中
c++语言版本
正在学习中
思考感悟
这道题注意边界判断,首先矩阵需要注意右上角和左下角,他们两个坐标同时满足两个边界判断,但是其实只能用一个边界判断,为什么呢?
因为数字13上面的9、5、1都是j-1会出界,他们需要向下走,而13是转折,14、15、16都是向右走,所以13必须要和14、15、16走相同的判断。
但是如果发散一下,之字形如果是反着来的,从16开始往回打印时应该怎么判断呢?此时应该先判断j-1,后判断i+1,将判断逻辑顺序反过来。
写在最后
方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!