红宝石 - 逆时针旋转矩阵n位置

Jam*_*amy 5 ruby arrays algorithm traversal multidimensional-array

给定2D矩阵:

matrix = [
   [  1,   2,   3,   4  ],
   [  5,   6,   7,   8  ],
   [  9,  10,  11,  12  ],
   [ 13,  14,  15,  16  ]
]
Run Code Online (Sandbox Code Playgroud)

我们如何逆时针旋转矩阵,以便像这样推动值?

matrix = [
   [  2,   3,   4,   8  ]
   [  1,   7,  11,  12  ]
   [  5,   6,  10,  16  ]
   [  9,  13,  14,  15  ]
]
Run Code Online (Sandbox Code Playgroud)

注意

这个问题不是重复this&this因为我想要做到的,是在逆时针旋转时尚的值.

我目前的实施和问题

我当前的实现仅以逆时针方式打印出值,但它不会旋转值.

  layers = [_rows, _cols].min / 2
  r1, r2, c3, c4 = 0, _rows, _cols, _cols
  new_matrix = Array.new(_rows + 1) { Array.new(_cols + 1) }
  (0..layers).each do |layer|
    row_top_left, row_bottom_left,  col_top_right, col_bottom_right = r1, r2, c3, c4
    result = []

    while row_top_left < row_bottom_left
      result << matrix[row_top_left][layer]
      row_top_left += 1
    end

    row_bottom_left = layer
    while row_bottom_left < col_bottom_right
      result << matrix[row_top_left][row_bottom_left]
      row_bottom_left += 1
    end

    temp_col_bottom_right = col_bottom_right
    temp_col_top_right = layer
    while col_bottom_right > temp_col_top_right
      result << matrix[col_bottom_right][temp_col_bottom_right]
      col_bottom_right -= 1
    end

    # p row_top_left
    tmp_row_top_left = layer
    while col_top_right > tmp_row_top_left
      result << matrix[tmp_row_top_left][col_top_right]
      col_top_right -= 1
    end
    p result.cycle



    r1 += 1
    r2 -= 1
    c3 -= 1
    c4 -= 1
Run Code Online (Sandbox Code Playgroud)

更新v0.1

关键的想法是矩阵需要以正确的方式旋转.例如,假设我们的矩阵需要2次旋转.因此:

   matrix_rotation(
       matrix.length - 1,      # rows
       matrix[0].length - 1,   # columns
       2,                      # Nom. of rotation
       matrix                  # The matrix
   )
Run Code Online (Sandbox Code Playgroud)
matrix = [ 
   #   Original               Iter: 1             Iter: 2  
  [ 1,   2,  3,  4 ],  # [ 2,  3,  4,  8 ]  # [ 3,  4,  8, 12 ]
  [ 5,   6,  7,  8 ],  # [ 1,  7, 11, 12 ]  # [ 2, 11, 10, 16 ]
  [ 9,  10, 11, 12 ],  # [ 5,  6, 10, 16 ]  # [ 1,  7,  6, 15 ]
  [ 13, 14, 15, 16 ]   # [ 9, 13, 14, 15 ]  # [ 5,  9, 13, 14 ]
]
Run Code Online (Sandbox Code Playgroud)

更新v0.2

数组的维度表示为:NxM其中N和M可以是任何数字,偶数或奇数.例如5x4,4,4,4x8等.

没有"空方块"这样的东西.

nas*_*eer 3

翻译:博士

\n\n

如果您想直接跳到解决方案代码,请跳到此答案的底部部分。

\n\n

解释

\n\n

你需要分解问题并独立解决每一个问题。

\n\n

问题

\n\n
    \n
  1. 获取层数
  2. \n
  3. 以反向螺旋形式循环以获得期望值
  4. \n
  5. 根据给定的旋转参数移动它们
  6. \n
\n\n

让我们分别讨论每一点:

\n\n
\n\n

获取层数

\n\n

您需要一种方法来获取层数。下面的矩阵有 2 层。如何?

\n\n

给定一个矩阵:

\n\n
       matrix           layers\n  --------------------------------\n |  1,  2,  3,  4  |   0  0  0  0 |\n |  5,  6,  7,  8  |   0  1  1  0 |\n |  9, 10, 11, 12  |   0  1  1  0 |\n | 13, 14, 15, 16  |   0  0  0  0 |\n  --------------------------------\n
Run Code Online (Sandbox Code Playgroud)\n\n

要查找层数,只需执行以下操作:

\n\n
[rows, cols].min / 2\n
Run Code Online (Sandbox Code Playgroud)\n\n

这样第一个问题就解决了。

\n\n
\n\n

以反向螺旋形式循环以获得期望值

\n\n

这部分需要很多思考。让我们想象一下:

\n\n
       matrix           layers\n  --------------------------------\n |  1,  2,  3,  4  |   \xe2\x86\x93  \xe2\x86\x90  \xe2\x86\x90  \xe2\x86\xb0 |   0  0  0  0 |\n |  5,  6,  7,  8  |   \xe2\x86\x93  1  1  \xe2\x86\x91 |   0  \xe2\x86\x93  \xe2\x86\xb0  0 |\n |  9, 10, 11, 12  |   \xe2\x86\x93  1  1  \xe2\x86\x91 |   0  \xe2\x86\xb3  \xe2\x86\x92  0 |\n | 13, 14, 15, 16  |   \xe2\x86\xb3  \xe2\x86\x92  \xe2\x86\x92  \xe2\x86\x92 |   0  0  0  0 |\n  --------------------------------\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是可以实现的。我们将有 4 个for循环。每个循环将处理:

\n\n
    \n
  1. (从上到下)
  2. \n
  3. 底部(从左到右)
  4. \n
  5. (从下到上)
  6. \n
  7. 顶部(从右到左)
  8. \n
\n\n

在进入循环之前,我们需要一些容器以螺旋形式存储我们的值。

\n\n

让我们有一个临时数组来存储值:

\n\n
       matrix           layers\n  --------------------------------\n |  1,  2,  3,  4  |   0  0  0  0 |\n |  5,  6,  7,  8  |   0  1  1  0 |\n |  9, 10, 11, 12  |   0  1  1  0 |\n | 13, 14, 15, 16  |   0  0  0  0 |\n  --------------------------------\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了便于解释,我们只研究最外层。(即第0层:

\n\n

第一个循环(左:从上到下)

\n\n
[rows, cols].min / 2\n
Run Code Online (Sandbox Code Playgroud)\n\n

注: 0表示第0层。

\n\n

第二个循环(底部:从左到右)

\n\n
       matrix           layers\n  --------------------------------\n |  1,  2,  3,  4  |   \xe2\x86\x93  \xe2\x86\x90  \xe2\x86\x90  \xe2\x86\xb0 |   0  0  0  0 |\n |  5,  6,  7,  8  |   \xe2\x86\x93  1  1  \xe2\x86\x91 |   0  \xe2\x86\x93  \xe2\x86\xb0  0 |\n |  9, 10, 11, 12  |   \xe2\x86\x93  1  1  \xe2\x86\x91 |   0  \xe2\x86\xb3  \xe2\x86\x92  0 |\n | 13, 14, 15, 16  |   \xe2\x86\xb3  \xe2\x86\x92  \xe2\x86\x92  \xe2\x86\x92 |   0  0  0  0 |\n  --------------------------------\n
Run Code Online (Sandbox Code Playgroud)\n\n

第三个循环(右:从下到上)

\n\n
# this array will get us the output of borders of the layer\nrow = []\n
Run Code Online (Sandbox Code Playgroud)\n\n

第四个循环(上:从右到左)

\n\n
# this loop will output the top-left side of the matrix\n# ==============================\n#  \xe2\x86\x93 [  1,  2,  3,  4 ]\n#  \xe2\x86\x93 [  5,  6,  7,  8 ]\n#  \xe2\x86\x93 [  9, 10, 11, 12 ]\n#  \xe2\x86\x93 [ 13, 14, 15, 16 ]\n# Output: [[1, 5, 9], [6] ]\n# ==============================\n(0...rows - 1 - layer).each do |i|\n  row << matrix[i][layer]\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

根据给定的旋转参数移动它们

\n\n

现在,我们得到了螺旋形式的值。但这个问题最重要的地方就在这一段。一个人如何转变价值观?有趣的是,我们将使用模。

\n\n

模数将在这里完成主要任务。它将允许我们根据旋转来移动值。但也给我们数组中正确的索引来开始移位。例如,如果我们要旋转 2 次:最外层为 2 % 12 = 2。

\n\n
# this loop will output the bottom side of the matrix\n# ==============================\n#  \xe2\x86\x93 [  1,  2,  3,  4 ]\n#  \xe2\x86\x93 [  5,  6,  7,  8 ]\n#  \xe2\x86\x93 [  9, 10, 11, 12 ]\n#  \xe2\x86\x93 [ 13, 14, 15, 16 ]\n#   \xe2\x86\xaa \xe2\x86\x92   \xe2\x86\x92   \xe2\x86\x92    \xe2\x86\x92\n# Output: [[1, 5, 9, 13, 14, 15], [6, 10]]\n# ==============================\n(0...cols - 1 - layer).each do |i|\n  row << matrix[rows - 1 - layer][i]\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

在移动值之前,让我们创建另一个包含正确值的矩阵:

\n\n
# this loop will output the right side of the matrix\n# ==============================\n#  \xe2\x86\x93 [  1,  2,  3,  4 ] \xe2\x86\x91\n#  \xe2\x86\x93 [  5,  6,  7,  8 ] \xe2\x86\x91\n#  \xe2\x86\x93 [  9, 10, 11, 12 ] \xe2\x86\x91\n#    [ 13, 14, 15, 16 ] \xe2\x86\x91\n#   \xe2\x86\xaa  \xe2\x86\x92   \xe2\x86\x92   \xe2\x86\x92   \xe2\x86\x92  \xe2\xa4\xbb\n# Output: [[1, 5, 9, 13, 14, 15, 16, 12, 8], [6, 10, 11]]\n# ==============================\n(rows - 1 - layer).step(0 + 1, -1).each do |i|\n  row << matrix[i][cols - 1 - layer]\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

我们将以相同的方式再次循环,但从 中的 idx 获取值row。例如:

\n\n
# this loop will output the top side of the matrix\n# ==============================\n#       \xe2\x86\x90   \xe2\x86\x90   \xe2\x86\x90   \xe2\x86\x90   \xe2\x86\xb0\n#  \xe2\x86\x93 [  1,  2,  3,  4 ] \xe2\x86\x91\n#  \xe2\x86\x93 [  5,  6,  7,  8 ] \xe2\x86\x91\n#  \xe2\x86\x93 [  9, 10, 11, 12 ] \xe2\x86\x91\n#    [ 13, 14, 15, 16 ] \xe2\x86\x91\n#   \xe2\x86\xaa  \xe2\x86\x92   \xe2\x86\x92   \xe2\x86\x92   \xe2\x86\x92  \xe2\xa4\xbb\n# Output: [[1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2], [6, 10, 11, 7]]\n# ==============================\n(cols - 1 - layer).step(0 + 1, -1).each do |i|\n  row << matrix[layer][i]\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

注: 0是第0层(为了解释起见)

\n\n

解决方案

\n\n
# row = [1, 5, 9, 13, 14, 15, 16, 12, 8, 4, 3, 2]\nshift = rotate % row.size\n# if we negate shift variable, we can get correct index\n# i.e. row[-2] = 3\nidx = -shift\n
Run Code Online (Sandbox Code Playgroud)\n