leetcode
leetcode 2551 ~ 2600
螺旋遍历二维数组

螺旋遍历二维数组

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 40 ms, 内存: 15.3 MB


/* 
 * 思路:
 * 1. 使用传统的方式构建一个螺旋遍历的列表。
 * 2. 将这个列表转化为Java Stream进行处理。
 */
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SpiralOrderStream {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> result = new ArrayList<>();
        if (matrix == null || matrix.length == 0) return result;
        int top = 0, bottom = matrix.length - 1;
        int left = 0, right = matrix[0].length - 1;

        while (top <= bottom && left <= right) {
            IntStream.rangeClosed(left, right).forEach(i -> result.add(matrix[top][i]));
            top++;
            IntStream.rangeClosed(top, bottom).forEach(i -> result.add(matrix[i][right]));
            right--;
            if (top <= bottom) IntStream.rangeClosed(left, right).map(i -> right - i + left).forEach(i -> result.add(matrix[bottom][i]));
            bottom--;
            if (left <= right) IntStream.rangeClosed(top, bottom).map(i -> bottom - i + top).forEach(i -> result.add(matrix[i][left]));
            left++;
        }
        return result.stream().collect(Collectors.toList());
    }
}

解释

方法:

该题解的主要思路是使用四个指针来标识二维数组的边界:左边界l,右边界r,上边界t,下边界b。初始化时,左边界和上边界设为0,右边界和下边界分别设为列数减一和行数减一。按照题目要求的螺旋顺序,从左到右遍历上边界行,然后下移上边界;从上到下遍历右边界列,然后左移右边界;从右到左遍历下边界行,然后上移下边界;从下到上遍历左边界列,然后右移左边界。每次遍历结束后,检查边界条件以决定是否继续遍历。如果某个方向的新边界越界,则结束螺旋遍历。

时间复杂度:

O(m*n)

空间复杂度:

O(1)

代码细节讲解

🦆
在遍历过程中,如何确保不会重复访问已经遍历过的元素?
在该螺旋遍历算法中,通过不断地调整四个边界(左、右、上、下)来确保不会重复访问元素。每完成一行或一列的遍历后,相应的边界会向内移动(例如,遍历完最上面一行后,上边界下移)。边界的调整保证了下一次遍历时,之前已遍历的行或列不会被再次访问。此外,通过在每次遍历后检查新的边界条件(如 'if t > b'),若新的边界无效,则停止遍历,避免了重复访问。
🦆
如果输入的二维数组是不规则的,例如某些行的列数不同,这种螺旋遍历算法是否仍然适用?
该螺旋遍历算法假设二维数组是规则的,即每一行的列数相同。如果二维数组是不规则的(某些行的列数不同),该算法可能无法正确运行,因为在遍历过程中可能会尝试访问不存在的索引,从而引发错误。针对不规则的二维数组,需要修改算法以检查每一行的实际列数,或者在实现前对数组进行规范化处理。
🦆
在代码中,边界的检查(例如 `if t > b`)是在每一步遍历后进行的,这种方式是否最优或存在更高效的处理边界的方法?
在螺旋遍历算法中,边界检查是必要的,因为它决定了遍历是否继续。在每个遍历步骤之后立即进行边界检查是有效的,因为它确保了即使数组大小变化,也不会导致访问越界。这种方法在逻辑上简单且直接,有助于维护代码的清晰性和正确性。尽管存在理论上的优化可能,如在循环开始前预计算条件,但在实际中这种优化可能带来的性能提升有限,而且会增加代码复杂度。
🦆
当二维数组为空或非常小(例如1x1,1x2)时,此算法的行为是怎样的?是否有必要对这些特殊情况进行额外处理?
当二维数组为空时,该算法在开始时检查数组长度,并直接返回空列表,这是适当的处理方式。对于非常小的数组如1x1或1x2,该算法同样有效。算法通过边界检查来适应不同大小的数组,避免了越界访问,并能正确输出小数组的螺旋遍历结果。因此,不需要对这些特殊情况进行额外处理,算法已经能够妥善处理这些场景。

相关问题