二维数组斜线输出算法------O(n)级 JAVA实现

算法输出顺序如下图(长宽不固定):    程序输出效果如右图(30为进循环次数,统计用):

先上代码

package learn;

public class XieXian {
	public static void main(String[] args) {
		int counter=0;	//遍历次数
		
		int[][] a= 
		{
				{9,5,1,2,4,4},
				{2,5,7,4,6,8},
				{7,5,1,7,5,5},
				{8,5,1,2,6,5},
				{5,7,3,5,1,8}
		};
		int n=a.length;
		int m=a[0].length;
		for(int i=0;i<=m+n-2;i++)
		{
			for(int x=0;  x<=i&&(x<n)&&i-x<m  ;x++)
			{counter++;
				System.out.print(a[x][i-x]);
				System.out.print("  ");
			}
			for(int y=m-1;  y>=0&&i-y>=0&&i-y<n&&i-y>0  ;y--)
			{counter++;
				System.out.print(a[i-y][y]);
				System.out.print("  ");
			}
			System.out.println("  ");
		}
		System.out.println(" ");
		System.out.print(counter);
	}
}

最上边定义的counter是记数用的, 每次循环都+1 , 用来计算时间复杂度, 

例子中的矩阵是5*6的的,共30个数,  可见输出结果counter记数30次, 时间复杂度是O(n)级别,

程序中用变量n表示行,m代表列, 由数组a确定

下边解释下算法思路:

做到二维数组的斜线输出也就是发现横纵坐标的规律

我们先按输出顺序写出前几个坐标来寻找下一规律.

(0,0)  (0,1)   (1,0)  (0,2)   (1,1)  (2,0)  (0,3)   (1,2)........

观察一下 横纵坐标的规律, 

不难发现 x+y的值 为0,1,1,2,2,2,3,3,3,3...

 

不止如此, 大家自己划一下可以发现,

第一条斜线上有一个数 ,对应 x+y为0

第二条斜线 有两个数对应 x+y为1

第三条斜线 有三个数对应 x+y为2

...................

还有在每一条斜线中的横坐标都是从零开始 一次一加一

这样,我们找到了x+y的规律, 还有x的规律, 也就得到了横纵坐标的规律,只要控制好不要越界就好

用for循环就能很好的控制每次从0 开始 每次加1,

外层循环控制 i=x+y,  每次+1代表一条斜线画完, i不会超过宽和高的和(下标从0开始, 所以小于m+n-2)

内层循环决定每条线怎么画:

也许大家会疑惑为什么内层是两个并列的for循环,  其实两个for不会同时执行,

第一个for是我们分析的结果, x控制横坐标, 从零开始增长,但是这样存在一个问题:

从这里开始斜线不再从第一排开始, 而我们的第一内层for循环的判断从0 开始,

到这一行,我们的x再从零开始的话发现 y的坐标越界了,

我们的for循环第一次检查这个点(上图红圆)发现越界从而终止了循环

换句话说上边的分析只能让我们输出半个矩阵,下半个不输出

既然我们能输出上半个相必下半个也是类似的方法吧

我们再次观察能发现半个矩形每条线都从右边开始,和上半个的从上边开始很类似, 

上半个是让x从零长, 下半个可以控制y从最大值每次-1呀,

通过分析发现x+y的值规律相同,也就是外层循环不用改,接着执行下一个for循环就可以了

这也就是一个外层for循环,两个内层for的来源,注意控制范围不要越界,

还有就是右上角开始的线既是上边的点,又是右边的点,  不控制的话会输出两遍,

所以我们第二个循环的横坐标从1开始就好了!

输出每一行是一条斜线

猜你喜欢

转载自blog.csdn.net/q5706503/article/details/82903498