Вращение матрицы NxN в Java
Это вопрос от взлома интервью. Решение говорит, что программа вращает внешние края, а затем внутренние края. Тем не менее, у меня возникли проблемы следуя логике обоих циклов for.
Может ли кто-нибудь объяснить логику кода (например, почему они делают "layer
Учитывая изображение, представленное матрицей NxN, где каждый пиксель в изображении составляет 4 байта, напишите метод поворота изображения на 90 градусов. Вы можете сделать это на месте?
public static void rotate(int[][] matrix, int n) {
for (int layer = 0; layer < n / 2; ++layer) {
int first = layer;
int last = n - 1 - layer;
for(int i = first; i < last; ++i) {
int offset = i - first;
int top = matrix[first][i]; // save top
// left -> top
matrix[first][i] = matrix[last-offset][first];
// bottom -> left
matrix[last-offset][first] = matrix[last][last - offset];
// right -> bottom
matrix[last][last - offset] = matrix[i][last];
// top -> right
matrix[i][last] = top; // right <- saved top
}
}
}
12 ответов
обзор
Рассмотрим пример матрицы, которая может выглядеть так:
ABCD
EFGH
IJKL
MNOP
В целях моего объяснения ABCD рассматривается как строка 0, EFGH - строка 1 и так далее. Первый пиксель строки 0 - это А.
Кроме того, когда я говорю о внешней оболочке, я имею в виду:
ABCD
E H
I L
MNOP
Сначала давайте посмотрим на код, который перемещает значения.
int top = matrix[first][i]; // save top
Первая строка кэширует значение в верхней позиции. Это относится к положению в верхнем ряду матрицы, обозначенной [first][i]. Например: сохранение A
,
// left -> top
matrix[first][i] = matrix[last-offset][first];
Следующая часть перемещает значение из левой позиции в верхнюю позицию. Например: принимая M
и положить его там, где A
является.
// bottom -> left
matrix[last-offset][first] = matrix[last][last - offset];
Следующая часть перемещает значение из нижней позиции в левую позицию. Например: принимая P
и положить его там, где M
является.
// right -> bottom
matrix[last][last - offset] = matrix[i][last];
Следующая часть перемещает значение из правой позиции в нижнюю позицию. Например: принимая D
и положить его там, где P
является.
// top -> right
matrix[i][last] = top; // right <- saved top
Последняя часть перемещает значение из кэша (какая была верхняя позиция) в правильную позицию. Например: положить A
с первого шага, где D
является.
Далее петли.
Внешний цикл выполняется от строки 0 до половины общего количества строк. Это связано с тем, что когда вы вращаете строку 0, она также поворачивает последнюю строку, а когда вы поворачиваете строку 1, она также поворачивает строку от второй к последней и так далее.
Внутренний цикл проходит от первой позиции пикселя (или столбца) в строке до последней. Имейте в виду, что для строки 0 это от пикселя 0 до последнего пикселя, но для строки 1 это от пикселя 1 до второго до последнего пикселя, поскольку первый и последний пиксели поворачиваются как часть строки 0,
Таким образом, первая итерация внешнего цикла заставляет внешнюю оболочку вращаться. Другими словами:
ABCD
EFGH
IJKL
MNOP
будет выглядеть так:
MIEA
NFGB
OJKC
PLHD
Посмотрите, как внешняя оболочка вращалась по часовой стрелке, но внутреннее ядро не двигалось.
Затем вторая итерация внешнего цикла вызывает вращение второй строки (исключая первый и последний пиксели), и мы в итоге получаем:
MIEA
NJFB
OKGC
PLHD
Я пишу этот ответ, потому что даже после прочтения ответа, опубликованного Джейсоном выше (это хорошо и помогло решить пару вопросов, которые у меня были), мне все еще не было ясно, какую роль играет переменная "смещение" в этой логике, поэтому потратив пару часов, чтобы понять это, я подумал поделиться этим со всеми.
Здесь используется много переменных, и важно понимать значение каждой из них.
Если вы посмотрите на переменную "first", она бесполезна, по сути это сам "слой", "first" вообще не изменяется во всей логике. Поэтому я удалил "первую" переменную (и она работает, читайте дальше).
Чтобы понять, как каждое из этих значений изменяется в каждой итерации внутреннего цикла for, я напечатал значения этих переменных. Посмотрите на вывод и поймите, какие значения меняются, когда мы перемещаемся из одного угла в другой во внутреннем цикле for, какие значения остаются постоянными при прохождении через один слой, а какие изменяются только при изменении слоя.
Одна итерация внутреннего цикла перемещает один единственный блок. Количество итераций, необходимых для перемещения одного слоя, будет меняться по мере нашего продвижения внутрь. Переменная 'last' делает эту работу за нас, она ограничивает внутренний цикл (ограничивает внутренний слой и мешает нам выйти за пределы оболочки, опираясь на номенклатуру, использованную Джейсоном)
Время изучать вывод.
Я использовал матрицу 6х6.
Input:
315 301 755 542 955 33
943 613 233 880 945 280
908 609 504 61 849 551
933 251 706 707 913 917
479 785 634 97 851 745
472 348 104 645 17 273
--------------Starting an iteration of OUTER FOR LOOP------------------
--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =0
buffer = 315
offset = i-layer = 0
Current Status:
472 301 755 542 955 315
943 613 233 880 945 280
908 609 504 61 849 551
933 251 706 707 913 917
479 785 634 97 851 745
273 348 104 645 17 33
--------------Finished an iteration of inner for loop------------------
--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =1
buffer = 301
offset = i-layer = 1
Current Status:
472 479 755 542 955 315
943 613 233 880 945 301
908 609 504 61 849 551
933 251 706 707 913 917
17 785 634 97 851 745
273 348 104 645 280 33
--------------Finished an iteration of inner for loop------------------
--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =2
buffer = 755
offset = i-layer = 2
Current Status:
472 479 933 542 955 315
943 613 233 880 945 301
908 609 504 61 849 755
645 251 706 707 913 917
17 785 634 97 851 745
273 348 104 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =3
buffer = 542
offset = i-layer = 3
Current Status:
472 479 933 908 955 315
943 613 233 880 945 301
104 609 504 61 849 755
645 251 706 707 913 542
17 785 634 97 851 745
273 348 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =4
buffer = 955
offset = i-layer = 4
Current Status:
472 479 933 908 943 315
348 613 233 880 945 301
104 609 504 61 849 755
645 251 706 707 913 542
17 785 634 97 851 955
273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Finished an iteration of OUTER FOR LOOP------------------
--------------Starting an iteration of OUTER FOR LOOP------------------
--------------Starting an iteration of inner for loop------------------
layer =1
last =4
i =1
buffer = 613
offset = i-layer = 0
Current Status:
472 479 933 908 943 315
348 785 233 880 613 301
104 609 504 61 849 755
645 251 706 707 913 542
17 851 634 97 945 955
273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Starting an iteration of inner for loop------------------
layer =1
last =4
i =2
buffer = 233
offset = i-layer = 1
Current Status:
472 479 933 908 943 315
348 785 251 880 613 301
104 609 504 61 233 755
645 97 706 707 913 542
17 851 634 849 945 955
273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Starting an iteration of inner for loop------------------
layer =1
last =4
i =3
buffer = 880
offset = i-layer = 2
Current Status:
472 479 933 908 943 315
348 785 251 609 613 301
104 634 504 61 233 755
645 97 706 707 880 542
17 851 913 849 945 955
273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Finished an iteration of OUTER FOR LOOP------------------
--------------Starting an iteration of OUTER FOR LOOP------------------
--------------Starting an iteration of inner for loop------------------
layer =2
last =3
i =2
buffer = 504
offset = i-layer = 0
Current Status:
472 479 933 908 943 315
348 785 251 609 613 301
104 634 706 504 233 755
645 97 707 61 880 542
17 851 913 849 945 955
273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Finished an iteration of OUTER FOR LOOP------------------
472 479 933 908 943 315
348 785 251 609 613 301
104 634 706 504 233 755
645 97 707 61 880 542
17 851 913 849 945 955
273 745 917 551 280 33
Извините, но нет другого способа, кроме как задуматься о том, как меняются значения layer, i и offset, чтобы понять, что здесь происходит.
Наконец код
Вот код, в котором я сначала удалил ненужные и добавил все операторы печати, на случай, если кто-то захочет больше играть. Этот код также имеет случайную матричную инициализацию и печать:
package com.crackingthecodinginterview.assignments.chap1;
public class Problem6RotateMatrix90 {
public static void main(String args[]){
int[][] matrix = new int[6][6];
initializeMatrix(matrix,6);
System.out.println("Input: ");
printMatrix(matrix,6);
rotate(matrix,6);
printMatrix(matrix,6);
}
public static void rotate(int[][] matrix, int n) {
for (int layer = 0; layer < n / 2; ++layer) {
System.out.println("\n--------------Starting an iteration of OUTER FOR LOOP------------------");
int last = n - 1 - layer;
for(int i = layer; i < last; ++i) {
int offset = i - layer;
int buffer = matrix[layer][i]; // save top
System.out.println("\n--------------Starting an iteration of inner for loop------------------");
System.out.println("layer ="+layer);
System.out.println("last ="+last);
System.out.println("i ="+i);
System.out.println("buffer = "+buffer);
System.out.println("offset = i-layer = "+ offset);
// left -> top
matrix[layer][i] = matrix[last-offset][layer];
// bottom -> left
matrix[last-offset][layer] = matrix[last][last - offset];
// right -> bottom
matrix[last][last - offset] = matrix[i][last];
// top -> right
matrix[i][last] = buffer; // right <- saved top
//print
System.out.println("Current Status: ");
printMatrix(matrix,6);
System.out.println("--------------Finished an iteration of inner for loop------------------");
}
System.out.println("--------------Finished an iteration of OUTER FOR LOOP------------------");
}
}
public static void printMatrix(int[][] matrix,int n){
System.out.print("\n");
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
System.out.print(" "+matrix[i][j]);
}
System.out.print("\n");
}
}
public static void initializeMatrix(int[][] matrix,int n){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
matrix[i][j]=(int) (Math.random() * 1000);
}
}
}
}
Только что увидел, что существует более простой способ написания кода путем рефакторинга "last - offset":
public static void rotateInPlace90DegreesClockwise(int[][] matrix) {
int n = matrix.length;
int half = n / 2;
for (int layer = 0; layer < half; layer++) {
int first = layer;
int last = n - 1 - layer;
for (int i = first; i < last; i++) {
int offset = i - first;
int j = last - offset;
int top = matrix[first][i]; // save top
// left -> top
matrix[first][i] = matrix[j][first];
// bottom -> left
matrix[j][first] = matrix[last][j];
// right -> bottom
matrix[last][j] = matrix[i][last];
// top -> right
matrix[i][last] = top; // right <- saved top
}
}
}
Проверьте это решение, чтобы сделать это на месте.
public void rotateMatrix(Pixel[][] matrix) {
for (int i = 0; i < matrix.length / 2; i++) {
for (int j = 0; j < matrix.length - 1 - 2 * i; j++) {
Pixel tmp = matrix[j + i][matrix.length - 1 - i];
matrix[j + i][matrix.length - 1 - i] = matrix[i][j + i];
matrix[i][j + i] = matrix[matrix.length - 1 - j - i][i];
matrix[matrix.length - 1 - j - i][i] = matrix[matrix.length - 1 - i][matrix.length - 1 - j - i];
matrix[matrix.length - 1 - i][matrix.length - 1 - j - i] = tmp;
}
}
}
В этом коде вы сможете повернуть матрицу NxN несколько раз, также вы можете выбрать направление 1 означает по часовой стрелке, -1 означает противоположное. В методе rotateMatrix вам понадобятся петли для каждого угла.
public class JavaApplication144 {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int matrix[][] = {{56, 12, 8, 90, 40}, {87, 76, 99, 1, 32}, {34, 43, 25, 78, 6}, {39, 555, 65, 88, 3}, {44, 75, 77, 14, 10}};
print();
}
вот метод:
static int[][] shiftingmatris(int[][] p_matris, int dırectıon) {
int[][] tempmatris = new int[p_matris.length][p_matris[0].length];
if (dırectıon == -1) {
for (int i = 0; i < p_matris.length; i++) {
for (int j = 0; j < p_matris[0].length; j++) {
if (i == 0 && j != p_matris[0].length - 1) {
tempmatris[i][j + 1] = p_matris[i][j];
} else if (i == p_matris.length - 1 && j != 0) {
tempmatris[i][j - 1] = p_matris[i][j];
}
}
}
for (int i = 0; i < p_matris.length; i++) {
for (int j = 0; j < p_matris[0].length; j++) {
if (j == 0 && i != 0) {
tempmatris[i - 1][j] = p_matris[i][j];
} else if (j == p_matris[1].length - 1 && i != p_matris.length - 1) {
tempmatris[i + 1][j] = p_matris[i][j];
}
}
}
} else if (dırectıon == 1) {
for (int i = 0; i < p_matris.length; i++) {
for (int j = 0; j < p_matris[1].length; j++) {
if (i == 0 && j != 0) {
tempmatris[i][j - 1] = p_matris[i][j];
} else if (i == p_matris.length - 1 && j != p_matris[0].length - 1) {
tempmatris[i][j + 1] = p_matris[i][j];
}
}
}
for (int i = 0; i < p_matris.length; i++) {
for (int j = 0; j < p_matris[0].length; j++) {
if (j == 0 && i != p_matris.length - 1) {
tempmatris[i + 1][j] = p_matris[i][j];
} else if (j == p_matris[0].length - 1 && i != 0) {
tempmatris[i - 1][j] = p_matris[i][j];
}
}
}
}
for (int i = 1; i < p_matris.length - 1; i++) {
for (int j = 1; j < p_matris[1].length - 1; j++) {
tempmatris[i][j] = p_matris[i][j];
}
}
return tempmatris;
}
}
Также вам потребуется распечатать матрицу. Таким способом возможно:
public static void print(){
Scanner s = new Scanner(System.in);
System.out.println("times of rotate: ");
int dondurme = s.nextInt();
System.out.println("direction?");
int dırectıon = s.nextInt();
int matrix[][] = {{56, 12, 8, 90, 40}, {87, 76, 99, 1, 32}, {34, 43, 25, 78, 6}, {39, 555, 65, 88, 3}, {44, 75, 77, 14, 10}};
System.out.println(" ");
for (int i = 0; i < matrix.length; i++) {
System.out.println(" ");
for (int j = 0; j < matrix.length; j++) {
System.out.print(" ");
System.out.print(matrix[i][j] + " ");
}
}
for (int i = 0; i < dondurme; i++) {
matrix = shiftingmatris(matrix, dırectıon);
}
System.out.println(" ");
for (int i = 0; i < matrix.length; i++) {
System.out.println(" ");
for (int j = 0; j < matrix.length; j++) {
System.out.print(" ");
System.out.print(matrix[i][j] + " ");
}
}
}
Вот мое решение в JavaScript, оно меняет значения между строкой и столбцом, начиная с верхнего правого края, и идет внутрь, пока не поменяется местами крайняя левая пара.
function rotateMatrix(arr) {
var n = arr.length - 1;
for (var i = 0; i < n; i++) {
for (var j = 0; j < n - i; j++) {
var temp = arr[i][j];
arr[i][j] = arr[n - j][n - i]; // top row
arr[n - j][n - i] = temp; // right column
}
}
return arr;
}
Да, этот код довольно уродлив и труден для чтения - прежде всего потому, что автор не использовал очень описательные имена переменных. Я решил ту же проблему, используя те же принципы (рассматривая квадратную матрицу как набор концентрических квадратов и затем вращая по одному, переходя от внешнего квадрата к внутреннему квадрату). Вот мое решение и объяснение моего мыслительного процесса.
Код
Я использовал C#, но синтаксис почти идентичен Java. После копирования / вставки просто изменитеa.Length
к a.length
и это должна быть синтаксически правильная Java.
void swap(int[][] a, int g, int h, int i, int j) {
int temp = a[g][h];
a[g][h] = a[i][j];
a[i][j] = temp;
}
int[][] rotateImage(int[][] a) {
if (a.Length > 1) {
int topRow = 0, bottomRow = a.Length - 1, leftCol = topRow, rightCol = bottomRow;
while (topRow < bottomRow && leftCol < rightCol) {
swap(a, topRow, leftCol, topRow, rightCol);
swap(a, topRow, leftCol, bottomRow, leftCol);
swap(a, bottomRow, leftCol, bottomRow, rightCol);
for (int i = topRow + 1, j = bottomRow - 1; i < bottomRow && j > topRow; i++, j--) {
swap(a, topRow, i, i, rightCol);
swap(a, topRow, i, bottomRow, j);
swap(a, topRow, i, j, leftCol);
}
topRow++; leftCol++;
bottomRow--; rightCol--;
}
}
return a;
}
Вы можете заметить, что я потенциально могу избавиться от переменных leftCol
а также rightCol
поскольку они равны topRow
а также bottomRow
С уважением. Причина, по которой я этого не делаю, заключается в том, что я чувствую, что это упрощает выполнение кода.
Объяснение
Во-первых, обратите внимание, что если задано 1x1
matrix, мы возвращаем исходную матрицу, потому что есть только один пиксель, что означает, что вращение не требуется.
Затем представьте, что нам даны следующие 2x2
матрица:
1 2
3 4
Вы можете повернуть эту матрицу за три перестановки. Top Left -> Top Right
, Top Left -> Bottom Left
, а также Top Left -> Bottom Right
.
4 1
2 3
А теперь представьте, что нам даны следующие 3x3
матрица:
1 2 3
4 5 6
7 8 9
Обратите внимание, что внутренний квадрат - это наш старый друг 1x1
матрица. Важно понимать, что все квадратные матрицы, гдеn > 1 && n % 2 != 0
в конечном итоге уменьшится до 1x1
в центре. Аналогично те, гдеn > 1 && n % 2 == 0
сократится до 2x2
в центре. Мы можем рассматривать оба случая одинаково.
Снова начнем с углов внешнего квадрата. Мы используем знакомые нам три предыдущих свопа:Top Left -> Top Right
, Top Left -> Bottom Left
, а также Top Left -> Bottom Right
.
7 2 1
4 5 6
9 8 3
Обратите внимание, что матрица почти повернута; это просто эти четыре досадных значения в центрах внешних сторон. Но также обратите внимание, что каждое из этих значений находится всего в одной позиции от углов, которые мы повернули. Если мы продолжим наш шаблон использования фиксированной начальной точки для наших свопов так же, как мы делали углы, мы могли бы повернуть последние четыре значения следующим образом:Top Middle -> Right Middle
, Top Middle -> Bottom Middle
, а также Top Middle -> Left Middle
. Что касается индексов, "Верхнее Среднее" - это просто "Верхнее левое" плюс один. Точно так же "Правый средний" - это просто "Верхний правый" плюс один. Для некоторых индексов имеет смысл начать с очень большого индекса (n - 1
) и декремент. Я называю меньший средний индексi
и больший средний индекс как j
.
7 4 1
8 5 2
9 6 3
Чтобы повернуть 2x2
матрица, шесть свопов для поворота 3x3
матрица, и вообще требуется n!
свопы, чтобы повернуть nxn
матрица. Мойwhile
цикл поворачивает углы для каждого концентрического квадрата в матрице (и каждый квадрат меньше, чем предыдущий квадрат), а затем мой for
loop заботится о значениях между углами по краям. Это продолжается до тех пор, пока не останется больше внутренних квадратов, которые нужно вращать, или пока не останется единственный внутренний квадрат.1x1
матрица.
Вот решение на C#. КаждыеN x N
матрица будет иметь пол (N/2)
квадратные циклы.
Например, оба 4×4
& 5×5
будет иметь 2 вращающихся слоя.
Следующая угловая комбинация определяет позиции:
(top,left) points to (first,first) --> 0,0
(top,right) points to (first,last) --> 0,n
(bottom,left) points to (last,first) --> n,0
(bottom,right) points to (last,last) --> n,n
Вот код для поворота матрицы на 90 градусов:
public static void RotateMatrixBy90Degress(int[][] matrix)
{
int matrixLen = matrix.Length;
for (int layer = 0; layer < matrixLen / 2; layer++)
{
int first = layer;
int last = matrixLen - first - 1;
for (int i = first; i < last; i++)
{
int offset = i - first;
int lastMinusOffset = last - offset;
// store variable in a temporary variable
int top = matrix[first][i];
// move values from left --> top
matrix[first][i] = matrix[lastMinusOffset][first];
// move values from bottom --> left
matrix[lastMinusOffset][first] = matrix[last][lastMinusOffset];
// move values from right --> bottom
matrix[last][lastMinusOffset] = matrix[i][last];
// move values from top --> right
matrix[i][last] = top;
}
}
}
Вот код для генерации случайных чисел в матрице.
public static void RotateMatrixImplementation(int len)
{
int[][] matrix = new int[len][];
var random = new Random();
for (int i = 0; i < matrix.Length; i++)
{
matrix[i] = new int[len]; // Create inner array
for (int j = 0; j < matrix[i].Length; j++)
{
//generate random numbers
matrix[i][j] = random.Next(1, Convert.ToInt32(Math.Pow(len, 3)));
}
}
RotateMatrixBy90Degress(matrix);
}
Вот мой 100% результат решения этой проблемы
Сначала я разбил 2D-массив на 1D arrayList послойно, затем повернул 1D-матрицу, а затем снова поместил в матричную форму. Разбив 2D-массив на 1D arrayList, я сохранил позиции элементов в массиве, чтобы мы могли разместить эту повернутую матрицу в этом позиция
import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
public class Solution {
static List<Integer[]> storePosition = new ArrayList<>();
public static ArrayList<Integer> rotateOneDArray(List<Integer> arr, int K) {
int[] A = arr.stream().mapToInt(i -> i).toArray();
// write your code in Java SE 8
int r = K % (A.length);
int[] ans = new int[A.length];
int y;
for (int i = 0; i < A.length; i++) {
y = i - r;
if (y < 0) {
y += A.length;
}
ans[y] = A[i];
}
return (ArrayList<Integer>) Arrays.stream(ans).boxed().collect(Collectors.toList());
}
static ArrayList<ArrayList<Integer>> getLinearMatrix(List<List<Integer>> matrix) {
ArrayList<ArrayList<Integer>> linear = new ArrayList<ArrayList<Integer>>();
int M = matrix.get(0).size();
int N = matrix.size();
int m = M, n = N, i, j, counter = 0;
Integer[] pos = new Integer[2];
while (m >= 2 && n >= 2) {
i = counter;
j = counter;
ArrayList<Integer> list = new ArrayList<>((m + n - 2) * 2);
while (j < M - counter) {
list.add(matrix.get(i).get(j));
pos = new Integer[2];
pos[0] = i;
pos[1] = j;
storePosition.add(pos);
++j;
}
--j;
++i;
while (i < N - counter) {
list.add(matrix.get(i).get(j));
pos = new Integer[2];
pos[0] = i;
pos[1] = j;
storePosition.add(pos);
++i;
}
--i;
--j;
while (j >= counter) {
list.add(matrix.get(i).get(j));
pos = new Integer[2];
pos[0] = i;
pos[1] = j;
storePosition.add(pos);
--j;
}
++j;
--i;
while (i > counter) {
list.add(matrix.get(i).get(j));
pos = new Integer[2];
pos[0] = i;
pos[1] = j;
storePosition.add(pos);
--i;
}
linear.add(list);
++counter;
m -= 2;
n -= 2;
}
return linear;
}
// Complete the matrixRotation function below.
static void matrixRotation(List<List<Integer>> matrix, int r) {
int m = matrix.get(0).size();
int n = matrix.size();
ArrayList<ArrayList<Integer>> linearMat = getLinearMatrix(matrix);
ArrayList<ArrayList<Integer>> rotatedLinearMat = new ArrayList<ArrayList<Integer>>();
for (int f = 0; f < linearMat.size(); f++) {
rotatedLinearMat.add(f, rotateOneDArray(linearMat.get(f), r));
}
int p = 0;
Integer[][] result = new Integer[n][m];
for (int i = 0; i < rotatedLinearMat.size(); ++i) {
for (int j = 0; j < rotatedLinearMat.get(i).size(); ++j) {
result[storePosition.get(p)[0]][storePosition.get(p)[1]] = rotatedLinearMat.get(i).get(j);
++p;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.print(result[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String[] mnr = bufferedReader.readLine().replaceAll("\\s+$", "").split(" ");
int m = Integer.parseInt(mnr[0]);
int n = Integer.parseInt(mnr[1]);
int r = Integer.parseInt(mnr[2]);
List<List<Integer>> matrix = new ArrayList<>();
IntStream.range(0, m).forEach(i -> {
try {
matrix.add(
Stream.of(bufferedReader.readLine().replaceAll("\\s+$", "").split(" "))
.map(Integer::parseInt)
.collect(toList())
);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
});
matrixRotation(matrix, r);
bufferedReader.close();
}
}
Простое решение:
int[][] a = { {00,01,02 }, { 10,11,12} ,{20,21,22}};
System.out.println(" lenght " + a.length);
int l = a.length;
for (int i = 0; i <l; i++) {
for (int j = l - 1; j >= 0; j--) {
System.out.println(a[j][i]);
}
}
Вот простое решение, которое идеально подходит для меня.
private int[][] rotateMatrix(int[][] matrix)
{
for(int i=0;i<matrix.length-1;i++)
{
for(int j =i;j<matrix[0].length;j++)
{
if(i!=j) {
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
}
return matrix;
}
/**
* @param args
*/
public static void main(String[] args) {
int n = 5; //5x5 matrix
int[][] matrixInitial = initMatrix(n);
int[][] matrixFinal = rotate(matrixInitial, n);
System.out.println(matrixFinal.length);
int m = 4; //4x4 matrix
int[][] matrixInitial2 = initMatrix(m);
int[][] matrixFinal2 = rotate(matrixInitial2, m);
System.out.println(matrixFinal2.length);
}
private static int[][] rotate(int[][] matrixInitial, int n) {
//it is much like square layers. each layer will be read and rotated
int layerCount = (n + 1) / 2;
System.out.println("n: " + n + " layerCount: " + layerCount);
int[][] matrixFinal = new int[n][n];
if (n % 2 == 1) { // for odd # layers the centre does not move
matrixFinal[n / 2][n / 2] = matrixInitial[n / 2][n / 2];
layerCount -= 1;
}
for (int i = 0; i < layerCount; i++) {
int width = n - (2 * i); // width of the layer
System.out.println("width: " + width);
int[] top = new int[width]; // read top
for (int j = 0; j < width; j++) {
top[j] = matrixInitial[i][i + j];
}
System.out.println("top: " + Arrays.toString(top));
//OK TOP TO RIGHT
for (int j = 0; j < width; j++) { // move top to right
matrixFinal[j+i][width-1+i] = top[j];
}
int[] tempLeft = new int[width]; // left will be read backwards
for (int j = 0; j < width; j++) { // reverse the temp
tempLeft[j] = matrixInitial[i + j][i];
}
int[] left = new int[width];
int indexTemp = 0;
for (int j = width-1; j >= 0; j--) { // move temp to left
left[indexTemp++] = tempLeft[j];
}
System.out.println("left: " + Arrays.toString(left));
//OK LEFT TO TOP
for (int j = 0; j < width; j++) { // move left to top
matrixFinal[i][j + i] = left[j];
}
int[] bottom = new int[width]; read bottom
for (int j = 0; j < width; j++) {
bottom[j] = matrixInitial[width - 1 + i][j + i];
}
System.out.println("bottom: " + Arrays.toString(bottom));
//OK BOTTOM TO LEFT
for (int j = 0; j < width; j++) { // move bottom to left
matrixFinal[j+i][i] = bottom[j];
}
int[] tempRight = new int[width]; // right will be read backwards
for (int j = 0; j < width; j++) {
tempRight[j] = matrixInitial[j + i][width - 1 + i];
}
int[] right = new int[width]; //reverse the temp
int indexTemp2 = 0;
for (int j = width; j > 0; j--) {
right[indexTemp2++] = tempRight[j - 1];
}
System.out.println("right: " + Arrays.toString(right));
//OK RIGHT TO BOTTOM
for (int j = 0; j < width; j++) { // move right to bottom
matrixFinal[width-1+i][j + i] = right[j];
}
}
for (int i = 0; i < n; i++) {
System.out.println(Arrays.toString(matrixFinal[i]));
}
return matrixFinal;
}
private static int[][] initMatrix(int n) { // init the matrix
int[][] matrix = new int[n][n];
int fill = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
matrix[i][j] = fill++;
}
}
for (int i = 0; i < n; i++) {
System.out.println(Arrays.toString(matrix[i]));
}
System.out.println("******");
return matrix;
}