Подтвердить что ты не робот

Вращение матрицы NxN в Java

Это вопрос от Cracking the Coding Interview. В решении говорится, что программа поворачивает внешние края, а затем внутренние края. Однако у меня возникают проблемы с логикой обоих циклов.

Может кто-нибудь объяснить логику кода (например, почему они делают "layer < n/2" и четыре шага "left → top" и "bottom → left" и т.д.)? На стороне примечания, как бы один мыслил процесс, когда придумывал это во время собеседования?

Учитывая изображение, представленное матрицей 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
        }
    }
}
4b9b3361

Ответ 1

Обзор

Рассмотрим образец матрицы, который может выглядеть так:

ABCD
EFGH
IJKL
MNOP

В целях моего объяснения ABCD рассматривается как строка 0, EFGH - это строка 1 и т.д. Первый пиксель строки 0 равен A.

Кроме того, когда я говорю о внешней оболочке, я имею в виду:

ABCD
E  H
I  L
MNOP

Сначала рассмотрим код, который перемещает значения.

    int top = matrix[first][i]; // save top

Первая строка кэширует значение в верхней позиции. Это относится к позиции в верхней строке матрицы, идентифицированной [первым] [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

Ответ 2

Я пишу этот ответ, потому что даже после прочтения ответа, опубликованного Джейсоном выше (это хорошо и помогло решить пару вопросов, которые у меня были), мне все еще не было ясно, какую роль играет переменная "смещение" в этой логике, поэтому потратив пару часов, чтобы понять это, я подумал поделиться этим со всеми.

Здесь используется много переменных, и важно понимать значение каждой из них.

Если вы посмотрите на переменную "first", она бесполезна, по сути, она сама "layer", "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, я и 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);
            }
        }
    }

}

Ответ 3

Просто увидел, что есть более простой способ написать код путем рефакторинга "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
          }
      }
  }

Ответ 4

проверьте это решение, чтобы сделать это на месте.

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;
        }
    }
}

Ответ 5

Здесь решение в С#. Каждая матрица 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);
    }

Ответ 6

Здесь мое решение в 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;
}

Ответ 7

Да, этот код довольно уродлив и труден для чтения - прежде всего потому, что автор не использовал очень описательные имена переменных. Я решил ту же проблему, используя те же принципы (рассматривая квадратную матрицу как набор концентрических квадратов, а затем вращая по одному, переходя от внешнего квадрата к внутреннему квадрату). Вот мое решение и объяснение моего мыслительного процесса.

Код

Я использовал С#, но синтаксис почти идентичен 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, мы возвращаем исходную матрицу, потому что есть только один пиксель, что означает, что вращение не требуется.

Далее, представьте, что нам дана следующая матрица 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. С точки зрения индексов, "Top Middle" - это просто "Top Left" плюс один. Точно так же "Правая середина" - это просто "Правая верхняя часть" плюс один. Для некоторых индексов имеет смысл начинать с чрезвычайно большого индекса (n - 1) и уменьшать его. Я имею в виду меньший средний индекс как i и больший средний индекс как j.

7 4 1
8 5 2
9 6 3

Она занимает три свопов вращать 2x2 матрицу, шесть свопов вращать 3x3 матрицу, и в целом она занимает n! меняет местами поворот матрицы nxn. Моя в while петля поворачивается углами для каждого концентрического квадрата в матрице (и каждый квадрат меньше, чем в предыдущем квадрате), а затем мой for цикла заботится о значениях в промежутке между углами по краям. Это продолжается до тех пор, пока не останется больше вращающихся внутренних квадратов или пока не останется только один внутренний квадрат - матрица 1x1.

Ответ 8

Здесь мое 100% -ое подчинение этой проблеме

Во-первых, я разбил 2D-массив на слой 1D arrayList, Затем вращается 1D матрица затем снова помещается в матрицу Разбивая 2D Arraylist на 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();
    }
}

Ответ 9

Простым решением является:

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]);
    }
}

Ответ 10

  /**
 * @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;
}

Ответ 11

Вот простое решение, которое отлично работает для меня.

 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;
    }