这是一个黑客等级问题(https://www.hackerrank.com/challenges/matrix-rotation-algo),需要将矩阵旋转R次。 矩阵是MxN
我提出的解决方案旋转每个环(外部 - >内部)。然而,这是非常低效的,并没有通过测试。
#!/usr/bin/ruby
def print_matrix(matrix)
matrix.each do |a|
a.each do |n|
print "#{n} "
end
puts
end
puts
end
def rotate_ring(matrix,s_i,s_j,m,n)
rotated = matrix.inject([]) { |a,element| a << element.dup }
for i in (s_i...m)
for j in (s_j...n)
case [i,j]
# Move items on corners
#Top Left Corner
when [s_i,s_j]
rotated[i+1][j] = matrix[i][j]
#Bottom Left Corner
when [m-1,s_j]
rotated[i][j+1] = matrix[i][j]
#Bottom Right Corner
when [m-1,n-1]
rotated[i-1][j] = matrix[i][j]
#Top Right Corner
when [s_i,n-1]
rotated[i][j-1] = matrix[i][j]
##################
# Move other items
# Top Row
when proc{|i,j| i == s_i and j>0 }
rotated[i][j-1] = matrix[i][j]
# Bottom Row
when proc{|i,j| i == m-1}
rotated[i][j+1] = matrix[i][j]
# Left Column
when proc{|i,j| i >= 0 and j == s_j}
rotated[i+1][j] = matrix[i][j]
# Right Column
when proc{|i,j| i >= 0 and j == n-1}
rotated[i-1][j] = matrix[i][j]
end
end
end
return rotated
end
def rotate_matrix(matrix,m,n,r)
s_i = 0
s_j = 0
min = ([m,n].min)/2
r.times do
for t in 0...min
matrix = rotate_ring(matrix,0+t,0+t,m-t,n-t)
end
end
return matrix
end
matrix = [['a','b','c','d'],
['e','f','g','h'],
['i','j','k','l'],
['m','n','o','p'],
['q','r','s','t']]
m = matrix.size
n = matrix[0].size
print_matrix(matrix)
print_matrix(rotate_matrix(matrix,m,n,1))
答案 0 :(得分:2)
<强>代码强>
def rotate_rings(arr, n)
m = arr.transpose.transpose
n.times { rotate_rings_once(m) }
m
end
def rotate_rings_once(arr)
nrings = (arr.size/2)
m = arr.transpose.transpose
4.times do
nrings.times { |i| arr[i][i..-i-1] = m[i][i+1..-i-1] << m[i+1][-i-1] }
rotate_array!(arr)
rotate_array!(m)
end
end
def rotate_array!(arr)
arr.replace(arr.map!(&:reverse).transpose)
end
<强>实施例强>
arr = [['a','b','c','d'],
['e','f','g','h'],
['i','j','k','l'],
['m','n','o','p'],
['q','r','s','t']]
rotate_rings(arr, 0)
#=> [["a", "b", "c", "d"],
# ["e", "f", "g", "h"],
# ["i", "j", "k", "l"],
# ["m", "n", "o", "p"],
# ["q", "r", "s", "t"]]
rotate_rings(arr, 1)
#=> [["b", "c", "d", "h"],
# ["a", "g", "k", "l"],
# ["e", "f", "o", "p"],
# ["i", "j", "n", "t"],
# ["m", "q", "r", "s"]]
rotate_rings(arr, 2)
#=> [["c", "d", "h", "l"],
# ["b", "k", "o", "p"],
# ["a", "g", "n", "t"],
# ["e", "f", "j", "s"],
# ["i", "m", "q", "r"]]
arr = [[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]
rotate_rings(arr, 0)
#=> [[ 1, 2, 3, 4, 5],
# [ 6, 7, 8, 9, 10],
# [11, 12, 13, 14, 15],
# [16, 17, 18, 19, 20]]
rotate_rings(arr, 1)
#=> [[ 2, 3, 4, 5, 10],
# [ 1, 8, 9, 14, 15],
# [ 6, 7, 12, 13, 20],
# [11, 16, 17, 18, 19]]
rotate_rings(arr, 2)
#=> [[ 3, 4, 5, 10, 15],
# [ 2, 9, 14, 13, 20],
# [ 1, 8, 7, 12, 19],
# [ 6, 11, 16, 17, 18]]
备注:强>
rotate_array!
是辅助方法,可以逆时针旋转其参数(数组)。例如:
m = [[10, 11, 12, 13],
[14, 15, 16, 17],
[18, 19, 20, 21],
[22, 23, 24, 25],
[26, 27, 28, 20]]
rotate_array!(m)
#=> [[13, 17, 21, 25, 20],
# [12, 16, 20, 24, 28],
# [11, 15, 19, 23, 27],
# [10, 14, 18, 22, 26]]`
rotate_array!
的返回值也是其参数m
的新值。如果我们轮换4
次,我们将返回原始数组。
目的:
m = arr.transpose.transpose
是制作arr
的深层副本,以便后者不会发生变异。我也可以使用:
m = arr.dup.map(:&dup)
在rotate_rings_once(arr)
,
nrings = (arr.size/2)
是数组中的环数。圈i
(i = 0, 1,..., nrings-1)
)的左上角元素是arr[i][i]
。对于每个环i
,环的顶行使用表达式计算:
arr[i][i..-i-1] = m[i][i+1..-i-1] << m[i+1][-i-1]
其中m
是在arr
元素移位之前计算的arr
的深层副本。
然后旋转数组arr
和m
,并移动arr
中每个环的(新)顶行的元素。这些计算重复了三次。