LeetCode(C++):二维数组

一:对角线遍历

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

 

示例:

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

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

解释:

思路一:

按遍历方向来按规律往结果res中添加数字,添加的顺序如下:

[0,0] -> [0,1],[1,0] -> [2,0],[1,1],[0,2] -> [1,2],[2,1] -> [2,2]

 

根据遍历的方向不同共分为五层,关键就是确定每一层的坐标范围:层数=m+n-1

下边界low = max(0, i - n + 1),这样可以保证下边界不会小于0,

上边界high = min(i, m - 1),这样保证了上边界不会大于m-1,

如果是偶数层,则从上边界往下边界遍历,反之如果是奇数层,则从下边界往上边界遍历

注意从matrix中取数字的坐标

代码:

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty()) return {};
        int m = matrix.size(), n = matrix[0].size(), k = 0;
        vector<int> res(m * n);
        for (int i = 0; i < m + n - 1; ++i)
        {
            int low = max(0, i - n + 1), high = min(i, m - 1);
            if (i % 2 == 0) //偶数层 向↙遍历
            {
                for (int j = high; j >= low; --j)
                {
                    res[k++] = matrix[j][i - j];
                }
            } 
            else //奇数层 向↗遍历
            {
                for (int j = low; j <= high; ++j) 
                {
                    res[k++] = matrix[j][i - j];
                }
            }
        }
        return res;
    }
};

 

思路二:

右上移动:坐标[-1, 1],左下移动:坐标[1, -1]

边界问题:左下角和右上角的位置越界需要改变两个坐标之外,其余的越界只需要改变一个。

同时改变两个坐标的越界情况,即在右上角和左下角的位置。如果在右上角位置还要往右上走时,那么要移动到它下面的位置的,那么:

如果row超过了m-1的范围,那么row重置为m-1,并且col自增2,然后改变遍历的方向。

如果col超过了n-1的范围,那么col重置为n-1,并且row自增2,然后改变遍历的方向。

一般的左边越界情况:如果row小于0,那么row重置0,然后改变遍历的方向。

                                        如果col小于0,那么col重置0,然后改变遍历的方向。

代码:

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty())
            return {};
        int m = matrix.size(), n = matrix[0].size();
        int r = 0, c = 0, k = 0;
        vector<int> res(m * n);
        vector<vector<int>> dirs{{-1,1}, {1,-1}};
        for (int i = 0; i < m * n; ++i) {
            res[i] = matrix[r][c];
            r += dirs[k][0];
            c += dirs[k][1];
            if (r >= m) {r = m - 1; c += 2; k = 1 - k;}
            if (c >= n) {c = n - 1; r += 2; k = 1 - k;}
            if (r < 0) {r = 0; k = 1 - k;}
            if (c < 0) {c = 0; k = 1 - k;}
        }
        return res;
    }
};

二、螺旋矩阵

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

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

示例 2:

输入:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

 

思路:

1   2   3                   

                +            6          +                    +             +            5

                              9                                          4

                                                  8   7                

 

上边:up=0,下边down=m-1,左边left=0,右边right=n-1

进行while循环,先遍历上边,将所有元素加入结果res,然后上边下移一位,如果此时上边大于下边,说明此时已经遍历完成了,直接break(即只有一行)。

同理对于下边,左边,右边

代码:
 

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        if (matrix.empty() || matrix[0].empty()) return {};
        int m = matrix.size(), n = matrix[0].size();
        vector<int> res;
        int up = 0, down = m - 1, left = 0, right = n - 1;
        while (true) {
            for (int j = left; j <= right; ++j) res.push_back(matrix[up][j]);
            if (++up > down) break;//只有一行
            for (int i = up; i <= down; ++i) res.push_back(matrix[i][right]);
            if (--right < left) break;//只有一列
            for (int j = right; j >= left; --j) res.push_back(matrix[down][j]);
            if (--down < up) break;//只有两行
            for (int i = down; i >= up; --i) res.push_back(matrix[i][left]);
            if (++left > right) break;//只有两列
        }
        return res;
    }
};

三、杨辉三角

给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。

在杨辉三角中,每个数是它左上方和右上方的数的和。

示例:

输入: 5
输出:
[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]

思路:特殊:输入1      输出[1]

                         输入2      输出[1,1]

           一般:x[i][j] = x[i-1][j] + x[i-1][j-1] 

代码:

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> res;
        if(numRows==0) return res;
        res.push_back(vector<int>(1,1));
        if(numRows==1) return res;
        res.push_back(vector<int>(2,1));
        if(numRows==2) return res;
        
        for(int i=2;i<numRows;i++)
        {
            vector<int> tmp(i+1,1);
            for(int j=1;j<i;j++)
            {
                tmp[j]=res[i-1][j-1]+res[i-1][j];
            }
            res.push_back(tmp);
        }
        return res;
    }
};
        
      

以上参考https://www.cnblogs.com/grandyang/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值