给定一个含有 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 ;
}
}
}
}