每日Leecode-498.对角线遍历c++

学习耗时:2h
给跪了,看了一个大佬的方法,一直没有反应过来,是我太笨了


给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
 
示例:输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]

输出:  [1,2,4,7,5,3,6,8,9]

解释:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-25Id4cts-1574304115365)(evernotecid://67870364-B5C3-4F4A-8FF1-2923A0094441/appyinxiangcom/27027923/ENResource/p10)]


解答:

(1)解题思路:

结合题目的图来看,得知:
1.每一趟对角线中元素的标号(x,y)相加的和是递增的。

第一趟:1的坐标(0,0),x+y=0;
第二趟:2的坐标(0,1),4的坐标(1,0)。x+y=1;
第三趟:7的坐标(2,0),5的坐标(1,1),3的坐标(0,1)。x+y=2;
第四趟:…

2.每一趟都是x或y其中一个从大到小(每次-1),另一个从小到大(每次+1)。

第二趟:2的坐标(0,1),4的坐标(1,0),x每次+1,y每次-1。
第三趟:7的坐标(2,0),5的坐标(1,1),3的坐标(0,1)。x每次-1,以每次+1。

3.确定初始值。例如这一趟是y从大到小,y尽量取最大,当初始值超过x上限时,不足的部分加到y上面。

第二趟:2的坐标(0,1),4的坐标(1,0),y的初始值取1,x取0.
第四趟:6的坐标(1,2),8的坐标(2,1),y的初始值取2,剩下的加到x上,x取1。

4.确定结束值。例如这一趟是x从大到小,这一趟结束的判断是,x减到0或y值达到上限。

第三趟:7的坐标(2,0),5的坐标(1,1),3的坐标(0,1)。x + y =2,x减到0为止。

5.这一趟是 x 从大到小,那么下一趟是 y 从大到小,循环进行。 并且方向相反时,逻辑处理是一样的,除了x,y和他们各自的上限值是相反的。
x从大到小,第三趟:7的坐标(2,0),5的坐标(1,1),3的坐标(0,1)。x+y=1,x初值取2,y初值取0,结束值x减到0为止。
x从小到大,第二趟:2的坐标(0,1),4的坐标(1,0),y的初始值取1,x取0,结束值y减到0为止。


规律变成代码

无论这一趟的方向是从左下到右上,还是从右上到左下,逻辑处理都是一样的,因此在换方向的时候,标志位进行更改。
bool bXFlag=true;
使用一个bool值标记,将用到的数据正确定位。例如:
//5.逻辑处理是一样的,x,y的上限值是相反的

int pm=bXFlag ? m : n;
int pn=bXFlag ? n : m;

这样就能保证逻辑计算的代码一样,数据不同。

以一趟未一个单元,那么i就是每一趟的和。
//1.坐标(x,y)相加的和是递增的

for(int i = 0; i < m +n;i++)

根据规律,就可以确定x和y的初值。
//3.当初是值超过x的上限时,不足的部分加到y上面

int x=(i<pm) ? i : pm-1;
int y=i-x;

每趟的结束条件。
//4.这一趟结束的判断是,x减到0或者y加到上限

while(x>=0&&y<pn)

一趟之中,x和y变化。
//2.每一趟都是x和y其中一个从大到小(每次-1),另一个从小到大(每次+1)

x--;y++;

输出数字。根据标志位变化
//5.方向相反时,x和y是相反的

nums.push_back(bXFlag?matrix[x][y]:matrix[y][x]);

这一趟结束了,循环起来,标志位变化。
下面是完整代码。

vector<int> findDiagonalOrder(vector<vector<int>>& matrix)
{
    vector<int>nums;
    int m=matrix.size();//二维数组的行数
    if(m==0) return nums;
    int n=matrix[0].size();//二维数组的列数
    if(n==0) return nums;
    
    bool bXFlag=true;
    for(int i=0;i<m+n;i++)
    {
        int pm=bXFlag?m:n;
        int pn=bXFlag?n:m;
        
        int x=(i>pm)?i:pm-1;
        itn y=i-x;
        
        while(x>=0&&y<pn)
        {
            nums.push_back(bXFlag?matrix[x][y]:matrix[y][x]);
            x--;
            y++;
        }
        bXFlag=!bXFlg;
    }
    return nums;
}

int main()
{
    int temp=1;
    int i,j;
    vector<vector<int>>array(3);//定义一个二维vector,行数为3.
    vector<int>ret;
    for(i=0;i<array.size();i++)
    {array[i].resize(3);}//对其每一行resize为3,及列数为3.
    for(i=0;i<array.size();i++)
    {
        for(j=0;j<array[0].size();j++)
        {
            array[i][j]=temp;
            temp++;
            cout<<array[i][j]<<" in"<<i<<","<<j<<endl;
        }
        cout<<endl;
    }
    ret=findDiagonalOrder(array);
    for(int i=0;i<ret.size();i++)
    {
        cout<<ret[i]<<endl;
    }
    return 0;
}

说到我为啥要写出来主函数,是因为这个答主的“坐标”和我理解的二维数组的元素“下标”不太一样,搞了半天没搞懂为啥他写点2的坐标是(1,0),是我太笨了,于是写了主函数出来验证一下二维vector的元素下表是否是正常理解的那样,而且手动推了一遍他的程序,最后才发现了**bXFlag=!bXFlg;**这个东西,很骚的一个操作,真的是我太笨了。。


原答案链接

https://leetcode-cn/problems/diagonal-traverse/solution/dui-jiao-xian-bian-li-fen-xi-ti-mu-zhao-zhun-gui-l/

答主GitHub

https://github.com/AhJo53589/leetcode-cn
学习向量(vector)
https://www.cnblogs.com/mr-wid/archive/2013/01/22/2871105.html
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

该用户没有用户名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值