LeetCode 54,59, 885 螺旋矩阵 Ⅰ Ⅱ Ⅲ 一招打遍所有螺旋遍历!

java 一套组合拳打遍所有螺旋遍历!

54. 螺旋矩阵

题目

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

示例 1:

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

四指针

使用四个指针记录当前要遍历的行/列

大循环内部:

  1. 向右:遍历第up行,从left -> right; up++,这一行结束;
  2. 向下:遍历第right列,从up -> down; right–,这一列结束;
  3. 向左:遍历第down行,从right -> left;down–,这一行结束;
  4. 向上:遍历第left列,从down -> up;left++,这一列结束。

由于矩形不规则,有可能在任意位置停止,因此每个小循环结束都需要判断下是否已经遍历结束。

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        int m = matrix.length, n = matrix[0].length;
        int up = 0, right = n - 1, down = m - 1, left = 0;
        while(true){
            for(int i = left; i <= right; i++) res.add(matrix[up][i]);
            up++;
            if(res.size() == m * n) return res;
            for(int i = up; i <= down; i++) res.add(matrix[i][right]);
            right--;
            if(res.size() == m * n) return res;
            for(int i = right; i >= left; i--) res.add(matrix[down][i]);
            down--;
            if(res.size() == m * n) return res;
            for(int i = down; i >= up; i--) res.add(matrix[i][left]);
            left++;
            if(res.size() == m * n) return res;
        }
    }
}

时间复杂度

O ( n ∗ m ) O(n * m) O(nm),遍历所有位置。

空间复杂度

O ( 1 ) O(1) O(1) 使用常数空间额外复杂度。

59. 螺旋矩阵 II

题目

给定一个正整数 n n n,生成一个包含 1 1 1 n 2 n_2 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

示例:

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

四指针

和上题类似,四个指针来遍历所有位置,使用 n u m num num记录即可,因为是规则正方形,每次肯定可以走完一圈,因此每次循环最后判断即可。

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];
        int up = 0, down = n - 1, left = 0, right = n - 1, num = 1;
        while(num <= n * n){
            for(int i = left; i <= right; i++) res[up][i] = num++;
            up++;
            for(int i = up; i <= down; i++) res[i][right] = num++;
            right--;
            for(int i = right; i >= left; i--) res[down][i] = num++;
            down--;
            for(int i = down; i >= up; i--) res[i][left] = num++;
            left++;
        }
        return res;
    }
}

时间复杂度

O ( n ∗ m ) O(n * m) O(nm),遍历所有位置。

空间复杂度

O ( 1 ) O(1) O(1) 使用常数空间额外复杂度。

885. 螺旋矩阵 III

题目

R R R C C C 列的矩阵上,我们从 ( r 0 , c 0 ) (r_0, c_0) (r0,c0) 面朝东面开始

这里,网格的西北角位于第一行第一列,网格的东南角位于最后一行最后一列。

现在,我们以顺时针按螺旋状行走,访问此网格中的每个位置。

每当我们移动到网格的边界之外时,我们会继续在网格之外行走(但稍后可能会返回到网格边界)。

最终,我们到过网格的所有 R ∗ C R * C RC 个空间。

按照访问顺序返回表示网格位置的坐标列表。

示例 1:

输入:R = 1, C = 4, r0 = 0, c0 = 0
输出:[[0,0],[0,1],[0,2],[0,3]]

image.png

四指针

忽略是否在界外,直接转圈,那么就相当于在遍历一个大正方形,额外实现一个 c h e c k check check方法,检查如果在界内就记录即可。

本题横竖需要走的格数遵从这样的规律 1 , 1 , 2 , 2 , 3 , 3 , 4 , 4 , . . . 1, 1, 2, 2, 3, 3, 4, 4, ... 1,1,2,2,3,3,4,4,...,因此可以使用两个变量 r o w row row, c o l col col来记录横竖需要走的距离,每次走完一条直线就自增1,简化写法。

class Solution {
    int R, C, idx = 1;
    int[][] res;
    void check(int r0, int c0){
        if(r0 >= 0 && r0 < R && c0 >= 0 && c0 < C){
            res[idx][0] = r0;
            res[idx++][1] = c0;
        }
    }
    public int[][] spiralMatrixIII(int R, int C, int r0, int c0) {
        this.R = R; this.C = C;
        res = new int[R * C][2];
        int row = 1, col = 1;
        res[0][0] = r0; res[0][1] = c0;
        while(idx < R * C){
            for(int i = 1; i <= row; i++) check(r0, ++c0);
            row++;
            for(int i = 1; i <= col; i++) check(++r0, c0);
            col++;
            for(int i = 1; i <= row; i++) check(r0, --c0);
            row++;
            for(int i = 1; i <= col; i++) check(--r0, c0);
            col++;
        }
        return res;
    }
}

时间复杂度

O ( m a x ( R , C ) 2 ) O(max(R, C) ^ 2) O(max(R,C)2),遍历所有位置。

空间复杂度

O ( 1 ) O(1) O(1) 使用常数空间额外复杂度。

我的博客:https://me.csdn.net/qq_20067165?ref=miniprofile

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于一棵树的后序遍历,我们首先遍历左子树,然后遍历右子树,最后访问根节点。根据这个顺序,我们可以借助一个栈来完成。 假设要输出根节点root到某一结点target的路径,首先,我们将root节点入栈。然后,进行以下循环: 1. 将栈顶节点弹出; 2. 如果栈顶节点的值等于target的值,则说明找到了目标结点,结束循环; 3. 如果栈顶节点的右子树不为空且右子树未被访问过,则将右子树入栈; 4. 如果栈顶节点的左子树不为空且左子树未被访问过,则将左子树入栈; 5. 如果栈顶节点的左右子树都为空,说明该结点是叶子节点,将其出栈。 最终,栈中保存的结点序列就是根节点到目标结点的路径。 下面是一个示例代码,假设树的节点定义如下: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None ``` ```python def postorderPath(root, target): if root is None: return [] stack = [] result = [] visited = set() stack.append(root) while stack: node = stack[-1] if node in visited: stack.pop() result.pop() else: visited.add(node) result.append(node.val) if node.val == target: break if node.right and node.right not in visited: stack.append(node.right) if node.left and node.left not in visited: stack.append(node.left) return result ``` 这样,调用`postorderPath(root, target)`函数即可得到根节点root到目标结点target的路径。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值