简体   繁体   English

由内而外的螺旋矩阵 Java

[英]Inside out Spiral Matrix Java

Given a N*N matrix;给定一个 N*N 矩阵; I want to print it in spiral form, that too inside out.我想以螺旋形式打印它,里面也一样。

eg.例如。

given a matrix给定一个矩阵

1  2  3  4
5  6  7  8
9  10 11  12
13 14 15 16

I want to print as 7 6 10 11 12 8 4 3 2 1 5 9 13 14 15 16我想打印为 7 6 10 11 12 8 4 3 2 1 5 9 13 14 15 16

Appreciate any help.感谢任何帮助。 Thanks.谢谢。

edit -编辑 -

Here is what I have done -这是我所做的 -

I have found the starting node based on N is even or odd.我发现基于 N 的起始节点是偶数或奇数。 I have found the relationship of traversal in each cycle based on row, column indexes - Left = -1, -3,-5 ... Down = +1,+3,+5 ... Right = +2,+4,+6 ... Up = -2,-4,-6 ...我根据行、列索引找到了每个循环中遍历的关系 - Left = -1, -3,-5 ... Down = +1,+3,+5 ... Right = +2,+4 ,+6 ... 向上 = -2,-4,-6 ...

But now I am struggling to put together this in code.但是现在我正在努力将其整合到代码中。

Finally I found the solution.最后我找到了解决方案。 Please let me know any optimized solution.请让我知道任何优化的解决方案。 There you go -你去吧——

public class SpiralMatrix {

public static void main(String[] args) {
    Scanner sc=new Scanner(System.in);

    int size=sc.nextInt();
    int[][] arr=new int[size][size];
    int r,c;
    int elements =size*size;

    for(int i=0;i<size;i++)
        for(int j=0;j<size;j++)
            arr[i][j]=sc.nextInt();

    int count=0;

    int left=-1,down=1,right=2,up=-2;

    if(size%2==0) {r=size/2-1; c=size/2;}       
    else r=c=size/2;
    System.out.print(arr[r][c]+" ");

    try{
    while(count<elements-1){
    for(int i=0;i>left;i--){
        c=c-1;
        System.out.print(arr[r][c]+" ");
        count++;
    }

    for(int i=0;i<down;i++){
        r=r+1;
        System.out.print(arr[r][c]+" ");
        count++;
    }

    for(int i=0;i<right;i++){
        c=c+1;
        System.out.print(arr[r][c]+" ");
        count++;
    }

    for(int i=0;i>up;i--){
        r=r-1;
        System.out.print(arr[r][c]+" ");
        count++;
    }

    left=left-2;
    down=down+2;
    right=right+2;
    up=up-2;

    }

    }catch(ArrayIndexOutOfBoundsException e){}

    }

} }

The general idea is to think of it as a checkerboard, where all the squares are painted in white.一般的想法是把它想象成一个棋盘,所有的方块都涂成白色。
You start by painting the square in the middle of the board in black.您首先将黑板中间的正方形涂成黑色。 You do the same for the square on the left.你对左边的正方形做同样的事情。
From there, you'll need to know if you continue painting to the left, or if you go down.从那里,您需要知道是继续向左绘画,还是向下绘画。 If the square down your current position is already painted in black, you continue to the left.如果您当前位置下方的方块已经涂成黑色,请继续向左移动。 Otherwise, you go down.否则,你下去。
To know if a square is already painted in black or not, you'll need a mask.要知道正方形是否已经涂成黑色,您需要一个面具。

Having this in mind, this is what I came up with, using only one loop.考虑到这一点,这就是我想到的,只使用一个循环。

I tried to comment the code enough, so it may seem too long... Anyway, I think it can still be shorten.我试图对代码进行足够的注释,所以它可能看起来太长了......无论如何,我认为它仍然可以缩短。

import java.util.*;

public class SpiralMatrix{

    public static final int UP = 0;
    public static final int LEFT = 1;
    public static final int RIGHT = 2;
    public static final int DOWN = 3;

     public static void main(String []args){        

        // The input matrix
        int[][] matrix= {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};

        // The input matrix  dimension
        int matrixLength = matrix.length;

        //The number of elemets of the input matrix
        int numberOfElements = matrixLength * matrixLength;

        // The output is a single dimensional array containing the elements of the input matrix as a spiral
        int[] spiralMatrix = new int[numberOfElements] ;

        // The matrix mask help to decide which is the next direction or the next element to pick from the input matrix
        // All the values of the mask are initialized to zero. 
        int[][] mask = new int[matrixLength][matrixLength];

                //The first element of the output(the spiral) is always the middle element of the input matrix
    int rowIndex = 0;
    int colIndex = 0;

    if(matrixLength%2 == 0){
        rowIndex = matrix.length/2 - 1;
    } else {
        rowIndex = matrix.length/2;
    }
    colIndex = matrix.length/2;

    // Each time an element from the input matrix is added to the output spiral, the corresponding element in the mask is set to 1
    spiralMatrix[0] = matrix[rowIndex][colIndex];
    mask[rowIndex][colIndex] = 1; 

        // The first direction is always to the left
        int nextDirection = LEFT;

        // This is a counter to loop through all the elements of the input matrix only one time
        int i = 0;

        while(i < numberOfElements - 1){    
            i++;

            // Check which direction to go (left, down, right or up)
            switch(nextDirection){

                case LEFT :
                    // From the input matrix, take the number at the left of the current position(which is the middle of the input matrix) and add it to the spiral
                    colIndex -=1;
                    spiralMatrix[i] = matrix[rowIndex][colIndex];

                    //Update the mask
                    mask[rowIndex][colIndex] = 1;

                    // Decide which direction(or element in the input matrix) to take next.
                    // After moving to the left, you only have two choices : keeping the same direction or moving down
                    // To know which direction to take, check the mask
                    if(mask[rowIndex+1][colIndex] == 1){
                        nextDirection = LEFT;
                    }else{
                        nextDirection = DOWN;
                    }
                    break;

                case DOWN : 
                    rowIndex +=1;
                    spiralMatrix[i] = matrix[rowIndex][colIndex];
                    mask[rowIndex][colIndex] = 1;
                    if(mask[rowIndex][colIndex+1] == 1){
                        nextDirection = DOWN;
                    }else{
                        nextDirection = RIGHT;
                    }
                    break;

                case RIGHT : 
                    colIndex +=1;
                    spiralMatrix[i] = matrix[rowIndex][colIndex];
                    mask[rowIndex][colIndex] = 1;
                    if(mask[rowIndex-1][colIndex] == 1){
                        nextDirection = RIGHT;
                    }else{
                        nextDirection = UP;
                    }
                    break;

                case UP : 
                    rowIndex -=1;
                    spiralMatrix[i] = matrix[rowIndex][colIndex];
                    mask[rowIndex][colIndex] = 1;
                    if(mask[rowIndex][colIndex-1] == 1){
                        nextDirection = UP;
                    }else{
                        nextDirection = LEFT;
                    }
                    break;  
            }
         }

         System.out.println(Arrays.deepToString(matrix));
         System.out.println(Arrays.deepToString(mask));
         System.out.println(Arrays.toString(spiralMatrix));
     }

}

You can debug it to see how the input matrix, the mask, and the output evolve at each iteration.您可以调试它以查看输入矩阵、掩码和输出在每次迭代中如何演变。 I only commented the first switch case, but let me know if further explanations are necessary for the others.我只评论了第一个开关案例,但如果其他人需要进一步解释,请告诉我。 Hope it helps.希望能帮助到你。

If you look at the movement of only 1 dimension of the spiral you'll see the pattern.如果您只查看螺旋线的 1 维的运动,您将看到图案。 eg.例如。 vertically, you move up 1, then down 2, then up 3, then down 4, etc. Then you just alternate between horizontal and vertical dimensions.在垂直方向上,您向上移动 1,然后向下移动 2,然后向上移动 3,然后向下移动 4,等等。然后您只需在水平和垂直维度之间交替。

Here is an example:下面是一个例子:

int[][] matrix = {{ 1, 2, 3, 4},
        { 5, 6, 7, 8},
        { 9,10,11,12},
        {13,14,15,16}};
int matrixLength = matrix.length * matrix[0].length;
int y = matrix.length/2 - 1;
int x = matrix[0].length/2 - 1;
System.out.println(matrix[y][x]);

boolean isDirectionDown = true;
boolean isDirectionRight = true;
boolean isMoveHorizontal = true;
int xLength = 1;
int yLength = 1;
int stepCount = 0;
outer: while (true) {
    if (isMoveHorizontal) {
        for (int i = 0; i < xLength; i++) {
            if (stepCount == matrixLength-1) {
                break outer;
            }
            x += (isDirectionRight) ? 1 : -1;
            stepCount++;
            System.out.println(matrix[y][x]);
        }
        xLength++;
        isDirectionRight = !isDirectionRight;
    }
    else {
        for (int i = 0; i < yLength; i++) {
            if (stepCount == matrixLength-1) {
                break outer;
            }
            y += (isDirectionDown) ? 1 : -1;
            stepCount++;
            System.out.println(matrix[y][x]);
        }
        yLength++;
        isDirectionDown = !isDirectionDown;
    }
    isMoveHorizontal = !isMoveHorizontal;
}

You would want to put the matrix into a two-dimensional array like so:您可能希望将矩阵放入二维数组中,如下所示:

int[][] matrix = {{ 1, 2, 3, 4},
                  { 5, 6, 7, 8},
                  { 9,10,11,12},
                  {13,14,15,16}};

Then, use some loops to create a spiralling algorithm.然后,使用一些循环来创建螺旋算法。 A typical square spiralling algorithm starts at a point then moves in a direction by x, turns 90 degrees and moves in that direction by x, then increments x by two, and repeats until it reaches the outer edge.典型的方形螺旋算法从一个点开始,然后沿 x 方向移动,旋转 90 度并沿该方向移动 x,然后将 x 增加 2,并重复直到到达外边缘。

Your outer loop may very well look something like this:您的外循环很可能如下所示:

for (int i=1; i<matrix.length; i+=2){
    ...
}

Also note that the number of movements your program will make should always be matrix.length*2-1 : so your loop could also look like this:另请注意,您的程序将进行的移动次数应始终为matrix.length*2-1 :因此您的循环也可能如下所示:

for (int i=0; i<matrix.length*2-1; i++){
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM