Как повернуть двумерный массив?
Я хотел бы добавить немного ndarray подробностей. В этом ответе 2d-array ключевые концепции повторяются, темп rectangular-arrays медленный и намеренно повторяющийся. Предлагаемое algorithm-design здесь решение не является 2d-array наиболее синтаксически компактным, однако 3d-array оно предназначено для тех, кто rectangular-arrays хочет узнать, что такое вращение algorithm-design матрицы и какова его реализация.
Во-первых, что algorithms такое матрица? Для целей multidimensional-array этого ответа матрица - это ndarray просто сетка, ширина и высота rectangular-arrays которой одинаковы. Обратите matrices внимание, что ширина и высота rectangular-arrays матрицы могут быть разными, но matrix для простоты в этом руководстве algorithm-design рассматриваются только матрицы matrices с одинаковой шириной и высотой algorithm (квадратные матрицы). И да, матрицы - это множественное matrix число матриц.
Примеры матриц: 2 rectangular-arrays × 2, 3 × 3 или 5 × 5. Или, в 2d-array более общем смысле, N × N. Матрица matrix 2 × 2 будет иметь 4 квадрата, потому nested-array что 2 × 2 = 4. Матрица 5 algorithm-design × 5 будет иметь 25 квадратов, потому multidimensional что 5 × 5 = 25. Каждый квадрат matrix называется элементом или multidimensional входом. Мы представим каждый matrix элемент точкой (.
) на диаграммах multidimensional-array ниже:
Матрица 2 × 2
. .
. .
Матрица matrix 3 × 3
. . .
. . .
. . .
Матрица 4 × 4
. . . .
. . . .
. . . .
. . . .
Итак, что matrix значит вращать матрицу? Давайте algorithms возьмем матрицу 2 × 2 и поместим matrices числа в каждый элемент, чтобы 3d-array можно было наблюдать за вращением:
0 1
2 3
Поворот 2d-array на 90 градусов дает нам:
2 0
3 1
Мы algorithms буквально повернули всю матрицу nested-array вправо, как руль автомобиля. Можно matrix подумать о «опрокидывании» матрицы algorithms на правую сторону. Мы хотим matrices написать функцию на Python, которая rectangular-arrays принимает матрицу и вращается 3d-array один раз вправо. Сигнатура matrices функции будет:
def rotate(matrix):
# Algorithm goes here.
Матрица будет ndarray определена с использованием multidimensional двумерного массива:
matrix = [
[0,1],
[2,3]
]
Следовательно, первая matrix позиция индекса обращается nested-array к строке. Вторая позиция algorithm индекса обращается к столбцу:
matrix[row][column]
Мы rectangular-arrays определим служебную функцию nested-array для печати матрицы.
def print_matrix(matrix):
for row in matrix:
print row
Один из rectangular-arrays способов поворота матрицы 2d-array - делать это послойно. Но 3d-array что такое слой? Представьте matrices себе лук. Так же, как слои multidimensional лука, по мере удаления каждого 3d-array слоя мы перемещаемся к центру. Другие algorithm-design аналогии - это Matryoshka doll или игра algorithm с передачей посылки.
Ширина 3d-array и высота матрицы определяют 2d-array количество слоев в этой матрице. Давайте multidimensional-array использовать разные символы matrices для каждого слоя:
Матрица multidimensional-array 2 × 2 имеет 1 слой
. .
. .
Матрица algorithm-design 3 × 3 состоит из 2 слоев
. . .
. x .
. . .
Матрица algorithm 4 × 4 состоит из 2 слоев
. . . .
. x x .
. x x .
. . . .
Матрица rectangular-arrays 5 × 5 состоит из 3 слоев
. . . . .
. x x x .
. x O x .
. x x x .
. . . . .
Матрица multidimensional-array 6 × 6 состоит из 3 слоев
. . . . . .
. x x x x .
. x O O x .
. x O O x .
. x x x x .
. . . . . .
Матрица algorithm-design 7 × 7 состоит из 4 слоев
. . . . . . .
. x x x x x .
. x O O O x .
. x O - O x .
. x O O O x .
. x x x x x .
. . . . . . .
Вы rectangular-arrays можете заметить, что увеличение nested-array ширины и высоты матрицы на algorithm единицу не всегда увеличивает 2d-array количество слоев. Взяв указанные algorithms выше матрицы и составив таблицу multidimensional слоев и размеров, мы видим, что nested-array количество слоев увеличивается multidimensional один раз на каждые два приращения rectangular-arrays ширины и высоты:
+-----+--------+
| N×N | Layers |
+-----+--------+
| 1×1 | 1 |
| 2×2 | 1 |
| 3×3 | 2 |
| 4×4 | 2 |
| 5×5 | 3 |
| 6×6 | 3 |
| 7×7 | 4 |
+-----+--------+
Однако не rectangular-arrays все слои нужно вращать. Матрица rectangular-arrays 1 × 1 одинакова до и после 2d-array поворота. Центральный слой algorithms 1 × 1 всегда один и тот же multidimensional до и после поворота, независимо rectangular-arrays от того, насколько велика multidimensional общая матрица:
+-----+--------+------------------+
| N×N | Layers | Rotatable Layers |
+-----+--------+------------------+
| 1×1 | 1 | 0 |
| 2×2 | 1 | 1 |
| 3×3 | 2 | 1 |
| 4×4 | 2 | 2 |
| 5×5 | 3 | 2 |
| 6×6 | 3 | 3 |
| 7×7 | 4 | 3 |
+-----+--------+------------------+
Учитывая матрицу matrix N × N, как мы можем программно ndarray определить количество слоев, которые multidimensional-array нам нужно повернуть? Если nested-array мы разделим ширину или высоту 2d-array на два и проигнорируем остаток, мы rectangular-arrays получим следующие результаты.
+-----+--------+------------------+---------+
| N×N | Layers | Rotatable Layers | N/2 |
+-----+--------+------------------+---------+
| 1×1 | 1 | 0 | 1/2 = 0 |
| 2×2 | 1 | 1 | 2/2 = 1 |
| 3×3 | 2 | 1 | 3/2 = 1 |
| 4×4 | 2 | 2 | 4/2 = 2 |
| 5×5 | 3 | 2 | 5/2 = 2 |
| 6×6 | 3 | 3 | 6/2 = 3 |
| 7×7 | 4 | 3 | 7/2 = 3 |
+-----+--------+------------------+---------+
Обратите matrix внимание, как N/2
соответствует nested-array количеству слоев, которые rectangular-arrays необходимо повернуть? Иногда rectangular-arrays количество поворачиваемых matrices слоев на единицу меньше общего algorithm количества слоев в матрице. Это 2d-array происходит, когда самый внутренний nested-array слой сформирован только из matrices одного элемента (т. Е. Матрицы multidimensional 1 × 1) и, следовательно, не matrix нужно поворачивать. Его просто multidimensional-array игнорируют.
Нам, несомненно, понадобится matrices эта информация в нашей функции multidimensional-array для поворота матрицы, поэтому ndarray давайте добавим ее сейчас:
def rotate(matrix):
size = len(matrix)
# Rotatable layers only.
layer_count = size / 2
Теперь matrix мы знаем, что такое слои algorithms и как определить количество algorithms слоев, которые действительно ndarray нужно повернуть, как изолировать ndarray один слой, чтобы мы могли nested-array его повернуть? Во-первых, мы multidimensional-array проверяем матрицу от самого multidimensional-array внешнего слоя внутрь до самого multidimensional-array внутреннего слоя. Матрица algorithms 5 × 5 состоит всего из трех ndarray слоев и двух слоев, которые multidimensional необходимо вращать:
. . . . .
. x x x .
. x O x .
. x x x .
. . . . .
Сначала multidimensional рассмотрим столбцы. Положение 3d-array столбцов, определяющих самый ndarray внешний слой, при условии, что multidimensional-array мы считаем от 0, равно 0 algorithm-design и 4:
+--------+-----------+
| Column | 0 1 2 3 4 |
+--------+-----------+
| | . . . . . |
| | . x x x . |
| | . x O x . |
| | . x x x . |
| | . . . . . |
+--------+-----------+
0 и 4 также являются algorithms позициями строк для самого 2d-array внешнего слоя.
+-----+-----------+
| Row | |
+-----+-----------+
| 0 | . . . . . |
| 1 | . x x x . |
| 2 | . x O x . |
| 3 | . x x x . |
| 4 | . . . . . |
+-----+-----------+
Так будет всегда, поскольку nested-array ширина и высота одинаковы. Поэтому algorithm мы можем определить положение 3d-array столбца и строки слоя всего multidimensional с двумя значениями (а не multidimensional с четырьмя).
Двигаясь внутрь algorithm-design ко второму слою, столбцы matrices располагаются на 1 и 3. И, да, как matrices вы уже догадались, для строк matrix то же самое. Важно понимать, что multidimensional нам нужно было как увеличивать, так multidimensional-array и уменьшать позиции строк ndarray и столбцов при переходе к algorithm следующему слою.
+-----------+---------+---------+---------+
| Layer | Rows | Columns | Rotate? |
+-----------+---------+---------+---------+
| Outermost | 0 and 4 | 0 and 4 | Yes |
| Inner | 1 and 3 | 1 and 3 | Yes |
| Innermost | 2 | 2 | No |
+-----------+---------+---------+---------+
Итак, чтобы multidimensional проверить каждый уровень, нам matrices нужен цикл с увеличивающимися multidimensional и уменьшающимися счетчиками, которые algorithm-design представляют движение внутрь, начиная rectangular-arrays с самого внешнего слоя. Мы algorithm-design назовем это нашей «петлей 2d-array слоев».
def rotate(matrix):
size = len(matrix)
layer_count = size / 2
for layer in range(0, layer_count):
first = layer
last = size - first - 1
print 'Layer %d: first: %d, last: %d' % (layer, first, last)
# 5x5 matrix
matrix = [
[ 0, 1, 2, 3, 4],
[ 5, 6, 6, 8, 9],
[10,11,12,13,14],
[15,16,17,18,19],
[20,21,22,23,24]
]
rotate(matrix)
Приведенный выше код multidimensional перебирает позиции (строки multidimensional и столбца) любых слоев, которые 3d-array необходимо повернуть.
Layer 0: first: 0, last: 4
Layer 1: first: 1, last: 3
Теперь algorithm-design у нас есть цикл, показывающий nested-array позиции строк и столбцов ndarray каждого слоя. Переменные 2d-array first
и last
определяют позицию индекса 2d-array первой и последней строк nested-array и столбцов. Возвращаясь к rectangular-arrays нашим таблицам строк и столбцов:
+--------+-----------+
| Column | 0 1 2 3 4 |
+--------+-----------+
| | . . . . . |
| | . x x x . |
| | . x O x . |
| | . x x x . |
| | . . . . . |
+--------+-----------+
+-----+-----------+
| Row | |
+-----+-----------+
| 0 | . . . . . |
| 1 | . x x x . |
| 2 | . x O x . |
| 3 | . x x x . |
| 4 | . . . . . |
+-----+-----------+
Таким multidimensional-array образом, мы можем перемещаться algorithm по слоям матрицы. Теперь multidimensional нам нужен способ навигации matrix внутри слоя, чтобы мы могли algorithm перемещать элементы по этому matrix слою. Обратите внимание: элементы algorithm-design никогда не «перепрыгивают» с 3d-array одного слоя на другой, но matrix они перемещаются внутри своих matrices соответствующих слоев.
Вращение algorithm каждого элемента в слое поворачивает multidimensional весь слой. Вращение всех ndarray слоев в матрице вращает всю matrix матрицу. Это очень важное ndarray предложение, поэтому постарайтесь multidimensional-array понять его, прежде чем двигаться rectangular-arrays дальше.
Теперь нам нужен способ multidimensional-array фактически перемещать элементы, то matrix есть вращать каждый элемент, а matrices затем слой и, наконец, матрицу. Для ndarray простоты мы вернемся к матрице ndarray 3x3, в которой есть один 3d-array вращаемый слой.
0 1 2
3 4 5
6 7 8
Наш цикл слоев multidimensional-array предоставляет индексы первого algorithm-design и последнего столбцов, а nested-array также первой и последней nested-array строк:
+-----+-------+
| Col | 0 1 2 |
+-----+-------+
| | 0 1 2 |
| | 3 4 5 |
| | 6 7 8 |
+-----+-------+
+-----+-------+
| Row | |
+-----+-------+
| 0 | 0 1 2 |
| 1 | 3 4 5 |
| 2 | 6 7 8 |
+-----+-------+
Поскольку наши матрицы algorithm-design всегда квадратные, нам нужны 2d-array только две переменные, first
и algorithm-design last
, поскольку позиции индексов 2d-array одинаковы для строк и столбцов.
def rotate(matrix):
size = len(matrix)
layer_count = size / 2
# Our layer loop i=0, i=1, i=2
for layer in range(0, layer_count):
first = layer
last = size - first - 1
# We want to move within a layer here.
Переменные rectangular-arrays first и last можно легко multidimensional использовать для ссылки на rectangular-arrays четыре угла матрицы. Это algorithm-design связано с тем, что сами углы multidimensional-array могут быть определены с использованием algorithm различных перестановок first
и algorithm last
(без вычитания, добавления matrices или смещения этих переменных):
+---------------+-------------------+-------------+
| Corner | Position | 3x3 Values |
+---------------+-------------------+-------------+
| top left | (first, first) | (0,0) |
| top right | (first, last) | (0,2) |
| bottom right | (last, last) | (2,2) |
| bottom left | (last, first) | (2,0) |
+---------------+-------------------+-------------+
По algorithms этой причине мы начинаем matrix вращение с четырех внешних algorithm углов - сначала мы повернем matrices их. Выделим их *
.
* 1 *
3 4 5
* 7 *
Мы хотим 3d-array поменять местами каждый *
на algorithms *
справа от него. Итак, давайте multidimensional распечатаем наши углы, определенные 3d-array с использованием только различных matrix перестановок first
и last
:
def rotate(matrix):
size = len(matrix)
layer_count = size / 2
for layer in range(0, layer_count):
first = layer
last = size - first - 1
top_left = (first, first)
top_right = (first, last)
bottom_right = (last, last)
bottom_left = (last, first)
print 'top_left: %s' % (top_left)
print 'top_right: %s' % (top_right)
print 'bottom_right: %s' % (bottom_right)
print 'bottom_left: %s' % (bottom_left)
matrix = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]
]
rotate(matrix)
Вывод должен 2d-array быть:
top_left: (0, 0)
top_right: (0, 2)
bottom_right: (2, 2)
bottom_left: (2, 0)
Теперь мы можем легко algorithms поменять местами каждый угол nested-array внутри нашего цикла слоя:
def rotate(matrix):
size = len(matrix)
layer_count = size / 2
for layer in range(0, layer_count):
first = layer
last = size - first - 1
top_left = matrix[first][first]
top_right = matrix[first][last]
bottom_right = matrix[last][last]
bottom_left = matrix[last][first]
# bottom_left -> top_left
matrix[first][first] = bottom_left
# top_left -> top_right
matrix[first][last] = top_left
# top_right -> bottom_right
matrix[last][last] = top_right
# bottom_right -> bottom_left
matrix[last][first] = bottom_right
print_matrix(matrix)
print '---------'
rotate(matrix)
print_matrix(matrix)
Матрица matrix перед поворотом углов:
[0, 1, 2]
[3, 4, 5]
[6, 7, 8]
Матрица nested-array после поворота углов:
[6, 1, 0]
[3, 4, 5]
[8, 7, 2]
Отлично! Мы nested-array успешно повернули каждый algorithms угол матрицы. Но мы не поворачивали 2d-array элементы в середине каждого algorithms слоя. Очевидно, нам нужен algorithm-design способ итерации внутри слоя.
Проблема nested-array в том, что единственный цикл 3d-array в нашей функции на данный multidimensional-array момент (цикл нашего слоя) перемещается multidimensional на следующий уровень на каждой matrices итерации. Поскольку наша matrices матрица имеет только один nested-array вращаемый слой, цикл слоев 2d-array завершается после поворота 2d-array только углов. Давайте посмотрим, что algorithms происходит с большей матрицей matrix 5 × 5 (где нужно вращать multidimensional два слоя). Код функции был 3d-array опущен, но остался таким 2d-array же, как указано выше:
matrix = [
[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19],
[20, 21, 22, 23, 24]
]
print_matrix(matrix)
print '--------------------'
rotate(matrix)
print_matrix(matrix)
Результат:
[20, 1, 2, 3, 0]
[ 5, 16, 7, 6, 9]
[10, 11, 12, 13, 14]
[15, 18, 17, 8, 19]
[24, 21, 22, 23, 4]
Неудивительно, что algorithm углы самого внешнего слоя rectangular-arrays были повернуты, но вы также 3d-array можете заметить, что углы multidimensional-array следующего слоя (внутрь) также matrices были повернуты. Это имеет 2d-array смысл. Мы написали код для matrices навигации по слоям, а также ndarray для поворота углов каждого algorithm слоя. Это похоже на прогресс, но, к algorithm сожалению, мы должны сделать algorithm-design шаг назад. Просто бесполезно multidimensional-array переходить к следующему слою, пока rectangular-arrays предыдущий (внешний) слой ndarray не будет полностью повернут. То algorithms есть до тех пор, пока каждый matrices элемент в слое не будет повернут. Вращать rectangular-arrays только углы не получится!
Сделайте ndarray глубокий вдох. Нам нужна multidimensional еще одна петля. Вложенный matrices цикл не меньше. Новый вложенный algorithm цикл будет использовать переменные multidimensional-array first
и last
, а также смещение для algorithm навигации внутри слоя. Мы 2d-array назовем этот новый цикл нашим algorithms «циклом элементов». Цикл matrices элементов будет посещать algorithm-design каждый элемент в верхнем ndarray ряду, каждый элемент в правом algorithms нижнем углу, каждый элемент multidimensional-array в нижнем ряду и каждый элемент rectangular-arrays в верхнем левом углу.
- Для перемещения вперед по верхней строке требуется столбец индекс, который нужно увеличить.
- Для перемещения вниз по правой стороне необходимо, чтобы индекс строки был увеличивается.
- Для движения назад по низу требуется столбец индекс, который нужно уменьшить.
- Для перемещения вверх влево необходимо, чтобы индекс строки был уменьшено.
Звучит matrices сложно, но это легко сделать, потому matrix что количество раз, которое algorithm-design мы увеличиваем и уменьшаем matrix для достижения вышеуказанного, остается rectangular-arrays неизменным по всем четырем ndarray сторонам матрицы. Например:
- Переместите 1 элемент в верхнюю строку.
- Переместить 1 элемент вниз с правой стороны.
- Переместить на 1 элемент назад по нижнему ряду.
- Переместить 1 элемент вверх влево.
Это rectangular-arrays означает, что мы можем использовать nested-array одну переменную в сочетании rectangular-arrays с переменными first
и last
для перемещения rectangular-arrays внутри слоя. Может быть полезно nested-array отметить, что перемещение 3d-array по верхнему ряду и вниз по ndarray правой стороне требует увеличения. При matrices движении назад по низу и rectangular-arrays вверх по левой стороне оба matrices требуют уменьшения.
def rotate(matrix):
size = len(matrix)
layer_count = size / 2
# Move through layers (i.e. layer loop).
for layer in range(0, layer_count):
first = layer
last = size - first - 1
# Move within a single layer (i.e. element loop).
for element in range(first, last):
offset = element - first
# 'element' increments column (across right)
top = (first, element)
# 'element' increments row (move down)
right_side = (element, last)
# 'last-offset' decrements column (across left)
bottom = (last, last-offset)
# 'last-offset' decrements row (move up)
left_side = (last-offset, first)
print 'top: %s' % (top)
print 'right_side: %s' % (right_side)
print 'bottom: %s' % (bottom)
print 'left_side: %s' % (left_side)
Теперь rectangular-arrays нам просто нужно назначить multidimensional-array верхнюю часть правой стороны, правую matrix сторону нижней части, нижнюю algorithm часть левой стороны и левую 3d-array сторону верхней части. Собирая ndarray все это вместе, получаем:
def rotate(matrix):
size = len(matrix)
layer_count = size / 2
for layer in range(0, layer_count):
first = layer
last = size - first - 1
for element in range(first, last):
offset = element - first
top = matrix[first][element]
right_side = matrix[element][last]
bottom = matrix[last][last-offset]
left_side = matrix[last-offset][first]
matrix[first][element] = left_side
matrix[element][last] = top
matrix[last][last-offset] = right_side
matrix[last-offset][first] = bottom
Учитывая rectangular-arrays матрицу:
0, 1, 2
3, 4, 5
6, 7, 8
Наша функция rotate
приводит matrix к:
6, 3, 0
7, 4, 1
8, 5, 2
algorithm
matrix
multidimensional-array
Как повернуть двумерный массив?
Мы используем файлы cookies для улучшения работы сайта. Оставаясь на нашем сайте, вы соглашаетесь с условиями использования файлов cookies. Чтобы ознакомиться с нашими Положениями о конфиденциальности и об использовании файлов cookie, нажмите здесь.