[Solution] 885. Spiral Matrix Ⅲ

  • Difficulty: Medium

Problem

On a 2 dimensional grid with R rows and C columns, we start at (r0, c0) facing east.

Here, the north-west corner of the grid is at the first row and column, and the south-east corner of the grid is at the last row and column.

Now, we talk in a clockwise spiral shape to visit every position in this grid.

Whenever we could move outside the boundary of the grid, we continue our walk outside the grid (but may return to the grid boundary later.)

Eventually, we reach all R * C spaces of the grid.

Return a list of coordinates representing the positions of the grid in the order they were visited.

Example 1:

Input: R = 1, C = 4, r0 = 0, c0 = 0
Output: [[0, 0], [0, 1], [0, 2], [0, 3]]

img

Example 2:

Input: R = 5, C = 6, r0 = 1, c0 = 4
Output: 
[[1, 4], [1, 5],
 [2, 5], [2, 4], [2, 3],
 [1, 3], [0, 3],
 [0, 4], [0, 5],
 [3, 5], [3, 4], [3, 3], [3, 2],
 [2, 2], [1, 2], [0, 2],
 [4, 5], [4, 4], [4, 3], [4, 2], [4, 1],
 [3, 1], [2, 1], [1, 1], [0, 1], 
 [4, 0], [3, 0], [2, 0], [1, 0], [0, 0]]

img

Note:

  1. 1 <= R <= 100
  2. 1 <= C <= 100
  3. 0 <= r0 < R
  4. 0 <= c0 < C

Math

Solution

题意就是给定一个矩阵大小和起始坐标,返回据此条件生成的螺旋方阵的路径,可以走到矩阵之外,但如果坐标落在矩阵之内,则要记录下来。比较容易想到的一个方法是模拟这样的一个走步过程。观察走螺旋的过程,可以发现其在每个方向上走过的距离依次是 [1, 1, 2, 2, 3, 3, ...],借助这个规律,就比较好模拟出来了。

public class Solution
{
    public int[][] SpiralMatrixIII(int R, int C, int r0, int c0)
    {
        int[][] ret = new int[R * C][];
        int i = 0;
        foreach (var coord in NextCoord(r0, c0))
        {
            if (0 <= coord.Item1 && coord.Item1 < R &&
                0 <= coord.Item2 && coord.Item2 < C)
            {
                ret[i++] = new int[] { coord.Item1, coord.Item2 };
            }
            if (i == R * C)
                break;
        }
        return ret;
    }

    private IEnumerable<Tuple<int, int>> NextCoord(int r, int c)
    {
        int step = 1;
        yield return new Tuple<int, int>(r, c);
        for( ; ; )
        {
            for (int i = 0; i < step; i++)
                yield return new Tuple<int, int>(r, ++c);
            for (int i = 0; i < step; i++)
                yield return new Tuple<int, int>(++r, c);
            step++;
            for (int i = 0; i < step; i++)
                yield return new Tuple<int, int>(r, --c);
            for (int i = 0; i < step; i++)
                yield return new Tuple<int, int>(--r, c);
            step++;
        }
    }
}
  • Note:这里使用到了 C♯ 中的 yield 关键字,有关这个的介绍,参见 MSDN 文档

另外还有一个可行的方法,就是对该矩阵内所有坐标进行排序(首先以其到 (r0, c0) 的距离排序,距离相同的,按照向量 \((r - r_0, c - c_0)^\mathrm{T}\) 与 x 轴正向的夹角大小排序),不过自己似乎写不出这样的代码,留待日后思量。

猜你喜欢

转载自www.cnblogs.com/Downstream-1998/p/10352613.html