• [OJ] Matrix Zigzag Traversal


    LintCode #46. Matrix Zigzag Traversal (Easy)

    class Solution {
    public:
        vector<int> printZMatrix(vector<vector<int> > &matrix) {
            vector<int> v;
            if (matrix.size() == 0) return v;
            int m = matrix.size(), n = matrix[0].size(), cnt = m * n;
            int i = 0, j = 0;
            int d[][2] = {{ -1, 1 }, { 1, -1 }};
            int dir = 0;
            while (v.size() < cnt) {
                while (i >= 0 && i < m && j >= 0 && j < n) {
                    v.push_back(matrix[i][j]);
                    i += d[dir][0];
                    j += d[dir][1];
                }
                i -= d[dir][0];
                j -= d[dir][1];
                if (dir == 0) {
                    if (j + 1 < n) ++j;
                    else ++i;
                } else {
                    if (i + 1 < m) ++i;
                    else ++j;
                }
                dir = (dir + 1) % 2;
            }
            return v;
        }
    };
    

    思路:

    • 斜着走的方向只有"右上"(dir=0)和"左下"(dir=1). 按"右上", "左下"的顺序交替走.
    • 当走到边界的时候, 要么"向右走一步", 要么"向下走一步".
      • 如果正在向"上"走, 优先"向走一步", 若不能则"向走一步".
      • 如果正在向"下"走, 优先"向走一步", 若不能则"向走一步".

    时间复杂度: O(m*n)
    空间复杂度: O(1)


    参照这篇博文的思路.

    class Solution {
    public:
        /**
         * @param matrix: a matrix of integers
         * @return: a vector of integers
         */
        vector<int> printZMatrix(vector<vector<int> > &matrix) {
            vector<int> v;
            if (matrix.size() == 0) return v;
            int m = matrix.size(), n = matrix[0].size();
            int sum = 0, x = 0, dx = -1;
            while (sum < m + n - 1) {
                while (x >= 0 && x < m && sum - x >= 0 && sum - x < n) {
                    v.push_back(matrix[x][sum - x]);
                    x += dx;
                }
                x -= dx;
                sum++;
                if ((dx == -1 && sum - x >= n)
                || (dx == 1 && x < m - 1)) {
                    ++x;
                }
                dx = -dx;
            }
            return v;
        }
    };
    

    思路:

    • 观察下标规律.
    (0, 0)
    (0, 1), (1, 0)
    (2, 0), (1, 1), (0, 2)
    (0, 3), (1, 2), (2, 1)
    (2, 2), (1, 3)
    (2, 3)
    

    可以看到各行xy坐标的和是常数, 且该和逐行递增.

    • 偶数行x递减, 奇数行x递增.
    • 原解法有个缺陷是"矩阵越细长, 空循环就越多". 我的解法对这点进行了优化.
      时间复杂度: O(m*n)
      空间复杂度: O(1)
  • 相关阅读:
    JavaScript中的事件循环
    CSS布局
    Tomcat相关
    C#参数中ref和out的区别
    angular启动4200端口后,如何停止监听4200端口
    表联接(交叉连接,内联,外联)
    如何使用vs自带的反编译工具Lldasm
    软件架构需要注意的几点,待补充。。。
    SqlServer中With(NOLOCK)
    TypeScript preview
  • 原文地址:https://www.cnblogs.com/7z7chn/p/5111760.html
Copyright © 2020-2023  润新知