leetcode练习 对角线遍历(二维数组)

给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。

示例:

输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
在这里插入图片描述
输出: [1,2,4,7,5,3,6,8,9]

解释:
思路,
说明:

给定矩阵中的元素总数不会超过 100000 。
上图,如
1 2 3
4 5 6
7 8 9
我们以对角线作为线索借助二维数组存储对角线,处理对角线,换成一维数组。
对角线的序列也就是二维数组的第一个下标numbers[i][],
我们先不考虑取对角线的方向,放在取完以后再分奇偶倒置。
我们的重点在于
1.对角线个数:我找的规律是行×列-1,想到这的同时我也想到了1×6这种情况
所以在代码中我将这两种情况区分了,对于前者依然遵循此规则,后者就是取
1也就是两者中小的一个hang>lie?lie:hang/
2.每条对角线的长度,也就是我们初始化二维数组中numbers[][j]的大小。
我们可以发现,对角线个数关于y=x个数对称,无论奇还是偶。所以我们以y=x包括
y=x作为分割线,取左上部分利用对称初始化数组。
numbers[i]=new int[i+1];
numbers[ceng-1-i]=new int[i+1] ;
在这里无论奇数还是偶数,偶数的化刚好,奇数好像多一个,
但是这个公式在奇数中到了结尾也就是最中间的时候上下两个式子
下标都一样,没事就是这个数组引用了两次新建的不同数组,被覆盖的那个
被虚拟机回收了,没事的,我们这样提高了通用性。
但是,随后我就被卡了一个测试点,就是3×5的矩阵,我发现这个规律有问题,
因为3×5对角线长度最多也就是3,但我的是4.于是我想是不是长度限制
在两者之间的较小数呢
有一下公式
numbers[i]=new int[i+1>t?t:i+1];
numbers[ceng-1-i]=new int[i+1>t?t:i+1] ;
这样就解决了这一问题,长度
3.内容
我的模拟办法是先从最顶部,也就是1 2 3从左上往右下取对角线。
(1)
我们设一个外循环来模拟列的移动,内循环来模拟存入的在数组中的位置
我们外循环会从1-3依次。
我们固定一次外循环,将外循环看成静态,看看内循环
我们内循环次数应该是这个对角线的长度,在第二点就已经解决了。
规律:我们内循环每次都是从0开始,如2【0】【1】 的移动,从2到4【1】【0】,行+1,和j同步,找规律最好找不变值(i+j=count),count是我们的层数
嘿嘿,层数现在起左用了。我们列方程求出列x+j=count.x=count-j.
for(int i=0;i<lie;i++,count++)
{//从列来取对角线
for(int j=0;j<numbers[count].length;j++)
{
numbers[count][j]=matrix[j][count-j];
}
}
再如3-7 [0] [2]–[1][1]–[2][0],都是第一个下标随j,第二个遵循此方程。
(2)3——9的模拟
我们的外循环i模拟的是6-9的移动,也就是行的变化,i代表行
我们来看6【1】【2】到8【2】【1】,我们也有规律,i+j==count。
我们内循环j的的增加也引起行的下移,我们的第一个下标规律是[j+i]也就是移动的行+行的起点,第二个下标也用方程解出来.
for(int i=1;i<hang;i++,count++)
{//从行取对角线
for(int j=0;j<numbers[count].length;j++)
{//i,j关系比较难想,先模拟一个坐标随i的变化在列方程(x+y=count)
numbers[count][j]=matrix[j+i][count-j-i];
}
}

class Solution {
    public int[] findDiagonalOrder(int[][] matrix) {
       if(matrix==null||matrix.length==0) 	//数组为空
    		return new int[0];						//建立一个空数组
    	else {
        int lie = matrix[0].length;				//行,列的大小
        int hang  = matrix.length;
        int ceng =hang+lie-1;		//一共需要多少层,也就是对角线的个数(观察所得)
        if(lie!=1&&hang!=1){		//这个特殊处理,比如1*6,层应该是1,不是1*6-1=5.
	        int [][]numbers=new int[ceng][];
	        for(int i=0;i<(ceng+1)>>1;i++) {
	        	//奇偶通吃
	        	int t=hang>lie?lie:hang;/*t是保存行和列两者之间小的一个
	        	之前每一层的元素个数找的规律有BUG,这是修正后的	*/
	        	//以下是对称赋予长度(关于y=x对称?)
	        	numbers[i]=new int[i+1>t?t:i+1];
	        	numbers[ceng-1-i]=new int[i+1>t?t:i+1] ;
	        }
	        int count=0;	//记录层数
	        for(int i=0;i<lie;i++,count++)
	        {//从列来取对角线
	        	for(int j=0;j<numbers[count].length;j++)
	        	{
	        		numbers[count][j]=matrix[j][count-j];
	        	}
	        }
	        for(int i=1;i<hang;i++,count++)
	        {//从行取对角线
	        	for(int j=0;j<numbers[count].length;j++)
	        	{//i,j关系比较难想,先模拟一个坐标随i的变化在列方程(x+y=count)
	        		numbers[count][j]=matrix[j+i][count-j-i];
	        	}
	        }
	        for(int i=0;i<numbers.length;i++)
	        {//对于奇偶对角线要区分
	        	if(i%2==0)
	        	{
	        		for(int j=0;j<numbers[i].length >>1;j++)
	        		{//倒置
	        			int t=numbers[i][j];
	        			numbers[i][j]=numbers[i][numbers[i].length-j-1];
	        			numbers[i][numbers[i].length-j-1]=t;
	        		}
	        	}
	        }
	        int nums[] =new int[lie*hang];//用来把二维转化成1维
	        int size=0;
	        for(int i=0;i<numbers.length;i++)
	        {
	        	for(int j=0;j<numbers[i].length;j++)
	        	{
	        		nums[size++]=numbers[i][j];
	        	}
	        }
	       
	       return nums ;
        }
        else {//这是对于1*6这种一个边为1的区分,这种规律特殊,应该只有一层也就是两者中小的
        	int numbers[]=new int[lie>hang?lie:hang];
        	int count=0;
        	for(int i=0;i<matrix.length;i++)
        	{
        		for(int j=0;j<matrix[i].length;j++)
        		{
        			numbers[count++]=matrix[i][j];
        		}
        	}
        	return numbers ;
           }
    }
 }
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值