development

나선형 순서로 2 차원 배열 인쇄

big-blog 2020. 12. 26. 16:27
반응형

나선형 순서로 2 차원 배열 인쇄


5x5 2 차원 배열을 나선형 순서로 어떻게 인쇄합니까?

나선형 순서로 모든 크기의 배열을 인쇄 할 수있는 공식이 있습니까?


아이디어는 행렬을 일련의 레이어, 오른쪽 상단 레이어 및 왼쪽 하단 레이어로 취급하는 것입니다. 매트릭스를 나선형으로 인쇄하기 위해이 매트릭스에서 레이어를 벗겨 내고 벗겨진 부분을 인쇄 한 다음 남은 부분의 인쇄물을 재귀 적으로 호출 할 수 있습니다. 재귀는 인쇄 할 레이어가 더 이상 없을 때 종료됩니다.

입력 매트릭스 :

1 2 3 4 
5 6 7 8
9 0 1 2   
3 4 5 6 
7 8 9 1

오른쪽 상단 레이어를 벗긴 후 :

 1 2 3 4 
       8
5 6 7  2
9 0 1  6   
3 4 5  1 
7 8 9

하위 매트릭스에서 왼쪽 하단 레이어를 벗긴 후 :

   6 7
5  0 1   
9  4 5
3 
7 8 9 

하위 매트릭스에서 오른쪽 상단 레이어를 벗긴 후 :

    6 7
      1   
   0  5
   4

하위 매트릭스에서 왼쪽 하단 레이어를 벗긴 후 :

  0
  4

재귀가 종료됩니다.


C 기능 :

// function to print the top-right peel of the matrix and 
// recursively call the print bottom-left on the submatrix.
void printTopRight(int a[][COL], int x1, int y1, int x2, int y2) {
    int i = 0, j = 0;

    // print values in the row.
    for(i = x1; i<=x2; i++) {
        printf("%d ", a[y1][i]);
    }

    // print values in the column.
    for(j = y1 + 1; j <= y2; j++)         {
        printf("%d ", a[j][x2]);
    }

    // see if more layers need to be printed.
    if(x2-x1 > 0) {
        // if yes recursively call the function to 
        // print the bottom left of the sub matrix.
        printBottomLeft(a, x1, y1 + 1, x2-1, y2);
    }
}

// function to print the bottom-left peel of the matrix and 
// recursively call the print top-right on the submatrix.
void printBottomLeft(int a[][COL], int x1, int y1, int x2, int y2) {
    int i = 0, j = 0;

    // print the values in the row in reverse order.
    for(i = x2; i>=x1; i--) {
        printf("%d ", a[y2][i]);
    }

    // print the values in the col in reverse order.
    for(j = y2 - 1; j >= y1; j--) {
        printf("%d ", a[j][x1]);
    }

    // see if more layers need to be printed.
    if(x2-x1 > 0) {
        // if yes recursively call the function to 
        // print the top right of the sub matrix.
        printTopRight(a, x1+1, y1, x2, y2-1);
    }
}

void printSpiral(int arr[][COL]) {
    printTopRight(arr,0,0,COL-1,ROW-1);
    printf("\n");
}

  1. 상단 행 팝
  2. 조옮김 및 거꾸로 뒤집기 (시계 반대 방향으로 90도 회전과 동일)
  3. 1로 이동

Python 코드 :

import itertools

arr = [[1,2,3,4],
       [12,13,14,5],
       [11,16,15,6],
       [10,9,8,7]]

def transpose_and_yield_top(arr):
    while arr:
        yield arr[0]
        arr = list(reversed(zip(*arr[1:])))

print list(itertools.chain(*transpose_and_yield_top(arr)))

나는 아무도 사용이없는 것을 볼 하나for loop재귀없이 코드에서, 나는 공헌 할 수 있도록.

아이디어는 다음과 같습니다.

(0,0) 지점, 즉 왼쪽 상단 모서리에 동쪽 (오른쪽)을 향하는 거북이가 있다고 상상해보십시오.

그것은 것입니다 앞으로 계속 각 시간이 표시를보고, 거북이는 것이다 우회전

따라서 오른쪽을 향한 지점 (0,0)에 거북이를 놓고 적절한 위치에 표지판을 배치하면 거북이가 나선형으로 배열을 횡단합니다.

이제 문제는 "어디에 표지판을 넣을까요?"입니다.

기호 (#로 표시, O로 표시)를 어디에 두어야하는지 봅시다 :

다음과 같은 그리드의 경우 :
OOOO
OOOO
OOOO
OOOO

우리는 다음과 같은 표시를합니다.
OOO #
#O #O
O # # O
# OO #

다음과 같은 그리드의 경우 :
OOO
OOO
OOO
OOO

우리는 다음과 같은 표시를합니다.
OO #
# #O
O # O
# O #

그리고 다음과 같은 그리드의 경우 :
OOOOOOO
OOOOOOO
OOOOOOO
OOOOOOO
OOOOOOO

우리는 다음과 같은 표시를합니다.
OOOOOO #
# OOOO # O
O # OO # OO
O # OOO # O
# OOOOO #

포인트는 왼쪽 상단 부분에하지 않는 한 우리는 징후는 점에서 장소, 즉 볼 수 가장 가까운 수평 경계까지의 거리와 가장 가까운 수직 경계가 동일는 반면, 왼쪽 상단 부분, 까지의 거리 상단 테두리는 왼쪽 테두리까지의 거리보다 하나 더 많으며, 지점이 수평 중앙에있는 경우 오른쪽 상단에 우선 순위가 부여되고 지점이 수직 중앙에있을 경우 왼쪽 상단에 우선 순위가 부여됩니다.

이것은 (최소 취함으로써, 아주 쉽게 간단한 함수에서 실현 될 수 curRowheight-1-curRow의), 다음 최소 ( curColwidth-1-curCol)과 그들이 같은 경우 비교합니다. 그러나 우리는 왼쪽 위의 경우, 즉 최소값이 curRowcurCol자체 인 경우를 고려해야 합니다. 이 경우 그에 따라 수직 거리를 줄입니다.

다음은 C 코드입니다.

#include <stdio.h>

int shouldTurn(int row, int col, int height, int width){
    int same = 1;
    if(row > height-1-row) row = height-1-row, same = 0; // Give precedence to top-left over bottom-left
    if(col >= width-1-col) col = width-1-col, same = 0; // Give precedence to top-right over top-left
    row -= same; // When the row and col doesn't change, this will reduce row by 1
    if(row==col) return 1;
    return 0;
}

int directions[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
void printSpiral(int arr[4][4], int height, int width){
    int directionIdx=0, i=0;
    int curRow=0, curCol=0;
    for(i=0; i<height*width; i++){
        printf("%d ",arr[curRow][curCol]);
        if(shouldTurn(curRow, curCol, height, width)){
            directionIdx = (directionIdx+1)%4;
        }
        curRow += directions[directionIdx][0];
        curCol += directions[directionIdx][1];
    }
    printf("\n");
}

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

출력되는 내용 :

12 34 8 12 16 15 14 1314 5678 11 10
12 34 8 12 11 10 9 5 6 7

세 가지 흥미로운 방법이 있습니다.

  1. 나선형으로 읽는 것은 경계를 향해 움직이고 경계 또는 그 자체에 부딪히는 뱀처럼 취급 될 수 있습니다 (N 반복의 단일 루프가 우아하고 가장 효율적이라는 것을 알았습니다)

    ar = [
         [ 0,  1,  2,  3, 4],
         [15, 16, 17, 18, 5],
         [14, 23, 24, 19, 6],
         [13, 22, 21, 20, 7],
         [12, 11, 10, 9, 8]]
    
    def print_spiral(ar):
        """
        assuming a rect array
        """
        rows, cols = len(ar), len(ar[0])
        r, c = 0, -1 # start here
        nextturn = stepsx = cols # move so many steps
        stepsy = rows-1
        inc_c, inc_r = 1, 0 # at each step move this much
        turns = 0 # how many times our snake had turned
        for i in range(rows*cols):
            c += inc_c
            r += inc_r 
    
            print ar[r][c],
    
            if i == nextturn-1:
                turns += 1
                # at each turn reduce how many steps we go next
                if turns%2==0:
                    nextturn += stepsx
                    stepsy -= 1
                else:
                    nextturn += stepsy
                    stepsx -= 1
                # change directions
                inc_c, inc_r = -inc_r, inc_c  
    
    print_spiral(ar)
    

산출:

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
  1. 재귀 적 접근 방식은 외부 레이어를 인쇄하고 내부 사각형에 대해 동일한 함수를 호출하는 것입니다.

    def print_spiral(ar, sr=0, sc=0, er=None, ec=None):
        er = er or len(ar)-1
        ec = ec or len(ar[0])-1
    
        if sr > er or sc > ec:
            print
            return
    
        # print the outer layer
        top, bottom, left, right = [], [], [], []
        for c in range(sc,ec+1):
            top.append(ar[sr][c])
            if sr != er:
                bottom.append(ar[er][ec-(c-sc)])
    
        for r in range(sr+1,er):
            right.append(ar[r][ec])
            if ec != sc:
                left.append(ar[er-(r-sr)][sc])
    
        print " ".join([str(a) for a in top + right + bottom + left]),
    
        # peel next layer of onion
        print_spiral(ar, sr+1, sc+1, er-1, ec-1)
    

마지막으로 효율적이지는 않지만 재미있는 작은 스 니펫이 있습니다. 기본적으로 맨 윗줄을 인쇄하고 전체 직사각형을 시계 반대 방향으로 회전하고 반복합니다.

def print_spiral(ar):
    if not ar: return
    print " ".join(str(a) for a in ar[0]),
    ar = zip(*[ reversed(row) for row in ar[1:]])
    print_spiral(ar)

이 프로그램은 모든 n * n 행렬에서 작동합니다.

public class circ {
    public void get_circ_arr (int n,int [][] a)
    {
        int z=n;
        {
            for (int i=0;i<n;i++)
            {
                for (int l=z-1-i;l>=i;l--)
                {
                    int k=i;
                    System.out.printf("%d",a[k][l]);
                }           

                for (int j=i+1;j<=z-1-i;j++)
                {
                    int k=i;
                    {
                        System.out.printf("%d",a[j][k]);
                    }
                }

                for (int j=i+1;j<=z-i-1;j++)
                {
                    int k=z-1-i;
                    {
                        System.out.printf("%d",a[k][j]);
                    }
                }

                for (int j=z-2-i;j>=i+1;j--)
                {
                    int k=z-i-1;        
                    {
                        System.out.printf("%d",a[j][k]);
                    }
                }
            }
        }
    }
}

도움이되기를 바랍니다.


루비를 배울 때이 문제에 집착했습니다. 이것이 제가 할 수있는 최선이었습니다.

def spiral(matrix)
  matrix.empty? ? [] : matrix.shift + spiral(matrix.transpose.reverse)
end

요점 의 개정판을 통해 뒤로 물러나 내 다른 솔루션 중 일부를 확인할 수 있습니다 . 또한 내가 요점을 포크 한 링크를 따라 가면 다른 영리한 솔루션을 찾을 수 있습니다. 여러 가지 우아한 방법, 특히 Ruby에서 해결할 수있는 정말 흥미로운 문제입니다.


자바 스크립트 솔루션 :

var printSpiral = function (matrix) {
  var i;
  var top = 0;
  var left = 0;
  var bottom = matrix.length;
  var right = matrix[0].length;

  while (top < bottom && left < right) {

    //print top 
    for (i = left; i < right; i += 1) {
      console.log(matrix[top][i]);
    }
    top++;

    //print right column
    for (i = top; i < bottom; i += 1) {
      console.log(matrix[i][right - 1]);
    }
    right--;

    if (top < bottom) {
      //print bottom
      for (i = right - 1; i >= left; i -= 1) {
        console.log(matrix[bottom - 1][i]);
      }
      bottom--;
    }

    if (left < right) {
      //print left column
      for (i = bottom - 1; i >= top; i -= 1) {
        console.log(matrix[i][left]);
      }
      left++;
    }
  }
};

한 가지 솔루션에는 오른쪽, 왼쪽, 위, 아래 방향 및 해당 제한 (인덱스)이 포함됩니다. 첫 번째 행이 인쇄되고 방향이 오른쪽에서 아래로 변경되면 상한을 증가시켜 행이 삭제됩니다. 마지막 열이 인쇄되고 방향이 왼쪽으로 변경되면 오른쪽 한계를 줄여 열이 삭제됩니다. 자세한 내용은 자명 한 C 코드에서 확인할 수 있습니다.

#include <stdio.h>
#define N_ROWS 5
#define N_COLS 3

void print_spiral(int a[N_ROWS][N_COLS])
{
    enum {up, down, left, right} direction = right;
    int up_limit = 0,
        down_limit = N_ROWS - 1,
        left_limit = 0,
        right_limit = N_COLS - 1,
        downcount = N_ROWS * N_COLS,
        row = 0,
        col = 0;

    while(printf("%d ", a[row][col]) && --downcount)
        if(direction == right)
        {
            if(++col > right_limit)
            {
                --col;
                direction = down;
                ++up_limit;
                ++row;
            }
        }
        else if(direction == down)
        {
            if(++row > down_limit)
            {
                --row;
                direction = left;
                --right_limit;
                --col;
            }
        }
        else if(direction == left)
        {
            if(--col < left_limit)
            {
                ++col;
                direction = up;
                --down_limit;
                --row;
            }
        }
        else /* direction == up */
            if(--row < up_limit)
            {
                ++row;
                direction = right;
                ++left_limit;
                ++col;
            }
}

void main()
{
    int a[N_ROWS][N_COLS] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    print_spiral(a);
}

테스트 및 다운로드 링크

.


문자 행렬이 주어지면 모든 문자를 먼저 바깥 쪽 원, 다음 원 순으로 인쇄하는 메서드를 구현합니다.

public static void printMatrixInSpiral(int[][] mat){

    if(mat.length == 0|| mat[0].length == 0){
        /* empty matrix */
        return;
    }

    StringBuffer str = new StringBuffer();
    int counter = mat.length * mat[0].length;
    int startRow = 0;
    int endRow = mat.length-1;
    int startCol = 0;
    int endCol = mat[0].length-1;
    boolean moveCol = true;
    boolean leftToRight = true;
    boolean upDown = true;

    while(counter>0){

        if(moveCol){

            if(leftToRight){

                /* printing entire row left to right */                 
                for(int i = startCol; i <= endCol ; i++){                       
                    str.append(mat[startRow][i]);
                    counter--;
                }
                leftToRight = false;
                moveCol = false;
                startRow++;
            }
            else{

                /* printing entire row right to left */
                for(int i = endCol ; i >= startCol ; i--){
                    str.append(mat[endRow][i]);
                    counter--;
                }
                leftToRight = true;
                moveCol = false;
                endRow--;       
            }
        }
        else
        {
            if(upDown){                 

                /* printing column up down */
                for(int i = startRow ; i <= endRow ; i++){                      
                    str.append(mat[i][endCol]);
                    counter--;
                }
                upDown = false;
                moveCol = true;
                endCol--;
            }
            else
            {

                /* printing entire col down up */
                for(int i = endRow ; i >= startRow ; i--){
                    str.append(mat[i][startCol]);
                    counter--;
                }
                upDown = true;
                moveCol = true;
                startCol++;
            }
        }
    }
    System.out.println(str.toString());
}

2 차원 N * N 행렬은 정사각형 행렬입니다.

생각:

나선형처럼 횡단하려면 4 개의 다른 방향으로 횡단해야합니다. 나선형의 한 층이 끝나면 매트릭스 내부를 횡단해야합니다. 따라서 총 5 개의 루프, 나선형처럼 횡단하는 4 개의 루프, 레이어를 통과하는 1 개의 루프가 필요합니다.

public void printSpiralForm(int[][] a, int length)
{

  for( int i = 0 , j = length-1 ; i < j ; i++ , j-- )
  {

    for( int k = i ; k < j ; k++ )
    {
      System.out.print( a[i][k] + " " ) ;
    }

    for( int k = i ; k < j ; k++ )
    {
      System.out.print(a[k][j] + " ");
    }

    for( int k = j ; k > i ; k-- )
    {
      System.out.print(a[j][k] + " ") ;
    }

    for( int k = j ; k > i ; k-- )
    {
      System.out.print( a[k][i] + " " ) ;
    }

  }

  if ( length % 2 == 1 )
  {
    System.out.println( a[ length/2 ][ length/2 ] ) ;
  }

}

간단하게->

public class spiralMatrix {

public static void printMatrix(int[][] matrix, int rows, int col)
{
    int rowStart=0;
    int rowEnd=rows-1;
    int colStart=0;
    int colEnd=col-1;

    while(colStart<=colEnd && rowStart<=rowEnd)
    {
        for(int i=colStart;i<colEnd;i++)
            System.out.println(matrix[rowStart][i]);

        for(int i=rowStart;i<rowEnd;i++)
            System.out.println(matrix[i][colEnd]);

        for(int i=colEnd;i>colStart;i--)
            System.out.println(matrix[rowEnd][i]);

        for(int i=rowEnd;i>rowStart;i--)
            System.out.println(matrix[i][colStart]);
        rowStart++;
        colEnd--;
        rowEnd--;
        colStart++;

    }

}
public static void main(String[] args){

    int[][] array={{1,2,3,4},{5,6,7,8}};
    printMatrix(array,2,4);
}

}


이것은 내 구현입니다.

public static void printMatrix(int matrix[][], int M, int N){
    int level = 0;
    int min = (M < N) ? M:N;
    System.out.println();
    while(level <= min/2){
        for(int j = level; j < N - level - 1; j++){
            System.out.print(matrix[level][j] + "\t");
        }
        for(int i = level; i < M - level - 1; i++) {
            System.out.print(matrix[i][N - level - 1] + "\t");
        }
        for(int j = N - level - 1; j > level; j--){
            System.out.print(matrix[M - level - 1][j] + "\t");
        }
        for(int i = M - level - 1; i > level; i-- ){
            System.out.print(matrix[i][level] + "\t");
        }
        level++;
    }
}

int N = Integer.parseInt (args [0]);

    // create N-by-N array of integers 1 through N
    int[][] a = new int[N][N];
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            a[i][j] = 1 + N*i + j;

    // spiral
    for (int i = N-1, j = 0; i > 0; i--, j++) {
          for (int k = j; k < i; k++) System.out.println(a[j][k]);
          for (int k = j; k < i; k++) System.out.println(a[k][i]);
          for (int k = i; k > j; k--) System.out.println(a[i][k]);
          for (int k = i; k > j; k--) System.out.println(a[k][j]);
   }

   // special case for middle element if N is odd
   if (N % 2 == 1) System.out.println(a[(N-1)/2][(N-1)/2]);
}

}


Slash Top Row-> Transpose-> Flip-> Repeat.

void slashTransposeFlip(int[][] m){

    if( m.length * m[0].length == 1){ //only one element left
        System.out.print(m[0][0]);
    }else{
        //print the top row
        for(int a:m[0]){System.out.print(a+" ");}

        //slash the top row from the matrix.
        int[][] n = Arrays.copyOfRange(m,1,m.length);

        int[][] temp = n;
        int rows = temp.length;
        int columns = temp[0].length;

        //invert rows and columns and create new array
        n = new int[columns][rows];

        //transpose
        for(int x=0;x<rows;x++)
            for(int y=0;y<columns;y++)
                n[y][x] = temp[x][y];

        //flipping time
        for (int i = 0; i < n.length / 2; i++) {
          int[] t = n[i];
          n[i] = n[n.length - 1 - i];
          n[n.length - 1 - i] = t;
        }

        //recursively call again the reduced matrix.
        slashTransposeFlip(n);
    }
}

복잡성 : 단일 트래버스 O(n)

복잡한 단일 루프 답변을 추가하겠습니다 O(n). 행렬의 왼쪽-오른쪽 및 오른쪽-왼쪽 탐색 중에 행 주요 인덱스에서 각각 1 씩 증가 및 감소하는 것을 관찰했습니다. 마찬가지로 상단 하단 및 하단 상단 트래버스의 경우 n_cols. 그래서 나는 그것을위한 알고리즘을 만들었다. 예를 들어, 행 주요 인덱스 항목이있는 (3x5) 행렬이 주어지면 인쇄 출력은 다음과 같습니다 1,2,3,4,5,10,15,14,13,12,11,6,7,8,9..

             ------->(+1)
          ^ 1  2  3  4  5   |
(+n_cols) | 6  7  8  9  10  | (-n_cols)
          | 11 12 13 14 15  
            (-1)<-------

코드 솔루션 :

#include <iostream>
using namespace std;

int main() {
    // your code goes here

    bool leftToRight=true, topToBottom=false, rightToLeft=false, bottomToTop=false;
    int idx=0;
    int n_rows = 3;
    int n_cols = 5;
    int cnt_h = n_cols, cnt_v = n_rows, cnt=0;
    int iter=1;
    for (int i=0; i <= n_rows*n_cols + (n_rows - 1)*(n_cols - 1)/2; i++){

        iter++; 
        if(leftToRight){
            if(cnt >= cnt_h){ 
                cnt_h--; cnt=0;
                leftToRight = false; topToBottom = true; 
                //cout  << "Iter: "<< iter << " break_leftToRight"<<endl;
            }else{
                cnt++;
                idx++;
                //cout << "Iter: "<< iter <<" idx: " << idx << " cnt: "<< cnt << " cnt_h: "<< cnt_h<< endl;
                cout<< idx << endl;
            }
        }else if(topToBottom){
            if(cnt >= cnt_v-1){
                cnt_v--; cnt=0;  
                leftToRight = false; topToBottom = false; rightToLeft=true;
                //cout  << "Iter: "<< iter  << " break_topToBottom"<<endl;
            }else{
                cnt++;
                idx+=n_cols;
                //cout  << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_v: "<< cnt_h<< endl;
                cout << idx <<endl;
            }
        }else if(rightToLeft){
            if(cnt >= cnt_h){
                cnt_h--; cnt=0; 
                leftToRight = false; topToBottom = false; rightToLeft=false; bottomToTop=true;
                //cout  << "Iter: "<< iter  << " break_rightToLeft"<<endl;
                //cout<< idx << endl;
            }else{
                cnt++;
                idx--;
                //cout  << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_h: "<< cnt_h<< endl;
                cout << idx <<endl;
            }
        }else if(bottomToTop){
            if(cnt >= cnt_v-1){
                cnt_v--; cnt=0;
                leftToRight = true; topToBottom = false; rightToLeft=false; bottomToTop=false;
                //cout  << "Iter: "<< iter << " break_bottomToTop"<<endl;
            }else{
                cnt++;
                idx-=n_cols;
                //cout  << "Iter: "<< iter << " idx: " << idx << " cnt: "<< cnt << " cnt_v: "<< cnt_h<< endl;
                cout<< idx << endl;
            }
        }

        //cout << i << endl;
    }


    return 0;
}

2D 매트릭스를 인쇄하려면 매트릭스를 직사각형 및 / 또는 작은 직사각형이 큰 직사각형에 맞춰지는 선의 구성으로 간주하고 각 레이어에서 매번 왼쪽 위 요소부터 시작하여 인쇄 할 직사각형을 형성하는 매트릭스의 경계를 선택합니다. ; 일단 이것으로 끝나면 더 작은 직사각형의 다음 레이어로 들어가십시오. 사각형이없는 경우 가로 또는 세로로 인쇄 할 선이어야합니다. 예제 매트릭스 HTH로 코드를 붙여 넣었습니다.

#include <stdio.h>

int a[2][4] = { 1, 2 ,3, 44,
                8, 9 ,4, 55 };

void print(int, int, int, int);

int main() {

int row1, col1, row2, col2;

row1=0;
col1=0;
row2=1;
col2=3;


while(row2>=row1 && col2>=col1)
{
    print(row1, col1, row2, col2);

    row1++;
    col1++;
    row2--;
    col2--;
}

return 0;
}


void print(int row1, int col1, int row2, int col2) {

int i=row1;
int j=col1;

/* This is when single horizontal line needs to be printed */
if( row1==row2 && col1!=col2) {
    for(j=col1; j<=col2; j++)
        printf("%d ", a[i][j]);
    return;
}

/* This is when single vertical line needs to be printed */
if( col1==col2 && row1!=row2) {
    for(i=row1; j<=row2; i++)
        printf("%d ", a[i][j]);
    return;
}


/* This is reached when there is a rectangle to be printed */

for(j=col1; j<=col2; j++)
    printf("%d ", a[i][j]);

for(j=col2,i=row1+1; i<=row2; i++)
    printf("%d ", a[i][j]);

for(i=row2,j=col2-1; j>=col1; j--)
    printf("%d ", a[i][j]);

for(j=col1,i=row2-1; i>row1; i--)
    printf("%d ", a[i][j]);

}

다음은 Java로 구현 한 것입니다.

public class SpiralPrint {
static void spiral(int a[][],int x,int y){

    //If the x and y co-ordinate collide, break off from the function

    if(x==y)
        return;
    int i;

    //Top-left to top-right

    for(i=x;i<y;i++)
        System.out.println(a[x][i]);

    //Top-right to bottom-right 

    for(i=x+1;i<y;i++)
        System.out.println(a[i][y-1]);

    //Bottom-right to bottom-left

    for(i=y-2;i>=x;i--)
        System.out.println(a[y-1][i]);

    //Bottom left to top-left

    for(i=y-2;i>x;i--)
        System.out.println(a[i][x]);

    //Recursively call spiral

    spiral(a,x+1,y-1);

}

public static void main(String[] args) {

    int a[][]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
    spiral(a,0,4);
    /*Might be implemented without the 0 on an afterthought, all arrays will start at 0 anyways. The second parameter will be the dimension of the array*/ 

    }

}

//shivi..coding is adictive!!
#include<shiviheaders.h>
#define R 3
#define C 6
using namespace std;

void  PrintSpiral(int er,int ec,int arr[R][C])
{
    int sr=0,sc=0,i=0;


    while(sr<=er && sc<=ec)
    {
        for(int i=sc;i<=ec;++i)
            cout<<arr[sr][i]<<" ";
        ++sr;

        for(int i=sr;i<=er;++i) 
            cout<<arr[i][ec]<<" ";
        ec--;

        if(sr<=er)  
        {
            for(int i=ec;i>=sc;--i)
                cout<<arr[er][i]<<" ";
            er--;   
        }

        if(sc<=ec)
        {
            for(int i=er;i>=sr;--i)
                cout<<arr[i][sc]<<" ";
            ++sc;   
        }

    }

}

int main()
{
    int a[R][C] = { {1,  2,  3,  4,  5,  6},
            {7,  8,  9,  10, 11, 12},
            {13, 14, 15, 16, 17, 18}
        };

        PrintSpiral(R-1, C-1, a);
}

누구든지 관심이 있다면 자바 코드.
입력 :
4
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 7

출력 : 1 2 3 4 8 3 4 5 6 7 9 5 6 7 2 1

public class ArraySpiralPrinter {

  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt(); //marrix size
    //read array
    int[][] ar = new int[n][n];
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < n; j++) {
        ar[i][j] = sc.nextInt();
      }
    }
    printTopRight(0, 0, n - 1, n - 1, ar);
  }
    //prints top and right layers.
  //(x1,y1) to (x1, y2) - top layer & (x1,y2) to (x2, y2)
  private static void printTopRight(int x1, int y1, int x2, int y2, int[][] ar) {
    //print row values - top
    for (int y = y1; y <= y2; y++) {
      System.out.printf("%d ", ar[x1][y]);
    }
    //print column value - right
    for (int x = x1 + 1; x <= x2; x++) {
      System.out.printf("%d ", ar[x][y2]);
    }

    //are there any remaining layers
    if (x2 - x1 > 0) {
      //call printBottemLeft
      printBottomLeft(x1 + 1, y1, x2, y2 - 1, ar);
    }
  }

    //prints bottom and left layers in reverse order
  //(x2,y2) to (x2, y1) - bottom layer & (x2,y1) to (x1, y1)
  private static void printBottomLeft(int x1, int y1, int x2, int y2, int[][] ar) {
    //print row values in reverse order - bottom
    for (int y = y2; y >= y1; y--) {
      System.out.printf("%d ", ar[x2][y]);
    }

    //print column value in reverse order - left
    for (int x = x2-1; x >= x1; x--) {
      System.out.printf("%d ", ar[x][y1]);
    }

    //are there any remaining layers
    if (x2 - x1 > 0) {
      printTopRight(x1, y1 + 1, x2 - 1, y2, ar);
    }
  }
}

이것은 내가 생각할 수있는 C의 재귀 버전입니다.

void printspiral  (int[][100],int, int, int, int);

int main()
{
  int r,c, i, j;
  printf ("Enter the dimensions of the matrix");
  scanf("%d %d", &r, &c);
  int arr[r][100];
  int min = (r<c?r:c);
  if (min%2 != 0) min = min/2 +1;
  for (i = 0;i<r; i++)
    for (j = 0; j<c; j++)
        scanf ("%d",&arr[i][j]);

  printspiral(arr,0,r,c,min );


}

void printspiral (int arr[][100], int i, int j, int k, int min)
{
   int a;

   for (a = i; a<k;a++)
   printf("%d\n", arr[i][a]);
   for (a=i+1;a<j;a++) 
   printf ("%d\n", arr[a][k-1]);
   for (a=k-2; a>i-1;a--)
   printf("%d\n", arr[j-1][a]);
   for (a=j-2; a>i; a--)
   printf("%d\n", arr[a][i]);
   if (i < min)
       printspiral(arr,i+1, j-1,k-1, min);

 }

http://www.technicalinterviewquestions.net/2009/03/print-2d-array-matrix-spiral-order.html

위의 답변에 대한 가장 좋은 설명은 다음과 같습니다. :) 다이어그램과 함께 :)


public static void printSpiral1(int array[][],int row,int col){

    int rowStart=0,colStart=0,rowEnd=row-1,colEnd=col-1;
    int i;

    while(rowStart<=rowEnd && colStart<= colEnd){

        for(i=colStart;i<=colEnd;i++)
            System.out.print(" "+array[rowStart][i]);   

        for(i=rowStart+1;i<=rowEnd;i++)
            System.out.print(" "+array[i][colEnd]); 

        for(i=colEnd-1;i>=colStart;i--)
            System.out.print(" "+array[rowEnd][i]); 

        for(i=rowEnd-1;i>=rowStart+1;i--)
            System.out.print(" "+array[i][colStart]);   

        rowStart++;
        colStart++;
        rowEnd--;
        colEnd--;
    }

}

public class SpiralPrint{

    //print the elements of matrix in the spiral order.
    //my idea is to use recursive, for each outer loop

    public static void printSpiral(int[][] mat, int layer){
        int up = layer;
        int buttom = mat.length - layer - 1;
        int left = layer;
        int right = mat[0].length - layer - 1;
        if(up > buttom+1 || left > right + 1)
            return; // termination condition

        //traverse the other frame, 
        //print up
        for(int i = left; i <= right; i ++){
            System.out.print( mat[up][i]+ " " );
        }
        //print right
        for(int i = up + 1; i <=buttom; i ++){
            System.out.print(mat[i][right] + " ");
        }

        //print buttom
        for(int i = right - 1; i >= left; i --){
            System.out.print(mat[buttom][i] + " ");
        }

        //print left
        for(int i = buttom - 1; i > up; i --){
            System.out.print(mat[i][left] + " ");
        }

        //recursive call for the next level
        printSpiral(mat, layer + 1);
    }

    public static void main(String[] args){

        int[][] mat = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}};
        int[][] mat2 = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}};
        SpiralPrint.printSpiral(mat2,0);
        return;
    }
}

다음은 C #의 솔루션입니다.

public static void PrintSpiral(int[][] matrix, int n)
{
    if (matrix == null)
    {
        return;
    }

    for (int layer = 0; layer < Math.Ceiling(n / 2.0); layer++)
    {
        var start = layer;
        var end = n - layer - 1;
        var offset = end - 1;

        Console.Write("Layer " + layer + ": ");

        // Center case
        if (start == end)
        {
            Console.Write(matrix[start][start]);
        }

        // Top
        for (int i = start; i <= offset; i++)
        {
            Console.Write(matrix[start][i] + " ");
        }

        // Right
        for (int i = start; i <= offset; i++)
        {
            Console.Write(matrix[i][end] + " ");
        }

        // Bottom
        for (int i = end; i > start; i--)
        {
            Console.Write(matrix[end][i] + " ");
        }

        // Left
        for (int i = end; i > start; i--)
        {
            Console.Write(matrix[i][start] + " ");
        }

        Console.WriteLine();
    }
}

Iterator를 사용하는 방법은 다음과 같습니다. 이것은 거의 동일한 문제를 해결합니다. 여기에 완전한 코드가 있습니다 : https://github.com/rdsr/algorithms/blob/master/src/jvm/misc/FillMatrix.java

import java.util.Iterator;

class Pair {
    final int i;
    final int j;

    Pair(int i, int j) {
        this.i = i;
        this.j = j;
    }

    @Override
    public String toString() {
        return "Pair [i=" + i + ", j=" + j + "]";
    }
}


enum Direction {
    N, E, S, W;
}


class SpiralIterator implements Iterator<Pair> {
    private final int r, c;
    int ri, ci;
    int cnt;

    Direction d; // current direction
    int level; // spiral level;

    public SpiralIterator(int r, int c) {
        this.r = r;
        this.c = c;

        d = Direction.E;
        level = 1;
    }

    @Override
    public boolean hasNext() {
        return cnt < r * c;
    }

    @Override
    public Pair next() {
        final Pair p = new Pair(ri, ci);
        switch (d) {
            case E:
                if (ci == c - level) {
                    ri += 1;
                    d = changeDirection(d);
                } else {
                    ci += 1;
                }
                break;

            case S:
                if (ri == r - level) {
                    ci -= 1;
                    d = changeDirection(d);
                } else {
                    ri += 1;
                }
                break;

            case W:
                if (ci == level - 1) {
                    ri -= 1;
                    d = changeDirection(d);
                } else {
                    ci -= 1;
                }
                break;

            case N:
                if (ri == level) {
                    ci += 1;
                    level += 1;
                    d = changeDirection(d);
                } else {
                    ri -= 1;
                }
                break;
        }

        cnt += 1;
        return p;
    }

    private static Direction changeDirection(Direction d) {
        switch (d) {
            case E:
                return Direction.S;
            case S:
                return Direction.W;
            case W:
                return Direction.N;
            case N:
                return Direction.E;
            default:
                throw new IllegalStateException();
        }
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

}


public class FillMatrix {
    static int[][] fill(int r, int c) {
        final int[][] m = new int[r][c];
        int i = 1;
        final Iterator<Pair> iter = new SpiralIterator(r, c);
        while (iter.hasNext()) {
            final Pair p = iter.next();
            m[p.i][p.j] = i;
            i += 1;
        }
        return m;
    }

    public static void main(String[] args) {
        final int r = 19, c = 19;
        final int[][] m = FillMatrix.fill(r, c);
        for (int i = 0; i < r; i++) {
            for (int j = 0; j < c; j++) {
                System.out.print(m[i][j] + " ");
            }
            System.out.println();
        }
    }
}

주어진 행 x 열이 있는 모든 2D 배열 행렬에 대한 완전한 순수 C 프로그램 .

#include <stdio.h>
void  printspiral(int *p,int r, int c) {    
    int i=0,j=0,m=1,n=0;
    static int firstrun=1,gCol;
    if (!p||r<=0||c<=0)
        return ;
    if(firstrun) {
        gCol=c;
        firstrun=0;
    }
    for(i=0,j=0;(0<=i && i<c)&&(0<=j && j<r);i+=m,j+=n) {                                                                               
        printf(" %d",p[i+j*gCol]);                                                                                                      
        if (i==0 && j==1 && (i+1)!=c) break;                                                                                            
        else if (i+1==c && !j) {m=0;n=1;}                                                                                               
        else if (i+1==c && j+1==r && j) {n=0;m=-1;}                                                                                     
        else if (i==0 && j+1==r && j) {m=0;n=-1;}                                                                                       
    }                                                                                                                                   
    printspiral(&p[i+j*gCol+1],r-2,c-2);                                                                                                
    firstrun=1;                                                                                                                         
    printf("\n");                                                                                                                       
}                                                                                                                                       
int main() {                                                                                                                            
    int a[3][3]={{0,1,2},{3,4,5},{6,7,8}};                                                                                              
    int b[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};                                                                                      
    int c[4][3]={{0,1,2},{3,4,5},{6,7,8},{9,10,11}};                                                                                    
    int d[3][1]={{0},{1},{2}};                                                                                                          
    int e[1][3]={{0,1,2}};                                                                                                              
    int f[1][1]={{0}};                                                                                                                  
    int g[5][5]={{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}};
    printspiral(a,3,3);                                                                                                                 
    printspiral(b,3,4);                                                                                                                 
    printspiral(c,4,3);                                                                                                                 
    printspiral(d,3,1);                                                                                                                 
    printspiral(e,1,3);                                                                                                                 
    printspiral(f,1,1);                                                                                                                 
    printspiral(g,5,5);
    return 0;                                                                                                                           
}

이 질문은 이것과 관련이 있습니다 : PHP의 매트릭스 배열 문제

제시된 답변은 작동하는 것처럼 보이지만 이해하기 복잡합니다. 이 문제를 해결하는 매우 간단한 방법은 나누고 정복하는 것입니다. 즉, 가장자리를 읽은 후 제거하면 다음 읽기가 훨씬 간단 해집니다. 아래의 PHP에서 완전한 솔루션을 확인하십시오.

#The source number matrix
$source[0] = array(1, 2, 3, 4);
$source[1] = array(5, 6, 7, 8);
$source[2] = array(9, 10, 11, 12);
$source[3] = array(13, 14, 15, 16);
$source[4] = array(17, 18, 19, 20);

#Get the spiralled numbers
$final_spiral_list = get_spiral_form($source);
print_r($final_spiral_list);


function get_spiral_form($matrix)
{
    #Array to hold the final number list
    $spiralList = array();

    $result = $matrix;
    while(count($result) > 0)
    {
        $resultsFromRead = get_next_number_circle($result, $spiralList);
        $result = $resultsFromRead['new_source'];
        $spiralList = $resultsFromRead['read_list'];
    }

    return $spiralList;
}


function get_next_number_circle($matrix, $read)
{
    $unreadMatrix = $matrix;

    $rowNumber = count($matrix);
    $colNumber = count($matrix[0]);

    #Check if the array has one row or column
    if($rowNumber == 1) $read = array_merge($read, $matrix[0]);
    if($colNumber == 1) for($i=0; $i<$rowNumber; $i++) array_push($read, $matrix[$i][0]);
    #Check if array has 2 rows or columns
    if($rowNumber == 2 || ($rowNumber == 2 && $colNumber == 2)) 
    {
        $read = array_merge($read, $matrix[0], array_reverse($matrix[1]));
    }

    if($colNumber == 2 && $rowNumber != 2) 
    {
        #First read left to right for the first row
        $read = array_merge($read, $matrix[0]);
        #Then read down on right column
        for($i=1; $i<$rowNumber; $i++) array_push($read, $matrix[$i][1]);
        #..and up on left column
        for($i=($rowNumber-1); $i>0; $i--) array_push($read, $matrix[$i][0]);
    }



    #If more than 2 rows or columns, pick up all the edge values by spiraling around the matrix
    if($rowNumber > 2 && $colNumber > 2)
    {
        #Move left to right
        for($i=0; $i<$colNumber; $i++) array_push($read, $matrix[0][$i]);
        #Move top to bottom
        for($i=1; $i<$rowNumber; $i++) array_push($read, $matrix[$i][$colNumber-1]);
        #Move right to left
        for($i=($colNumber-2); $i>-1; $i--) array_push($read, $matrix[$rowNumber-1][$i]);
        #Move bottom to top
        for($i=($rowNumber-2); $i>0; $i--) array_push($read, $matrix[$i][0]);
    }

    #Now remove these edge read values to create a new reduced matrix for the next read
    $unreadMatrix = remove_top_row($unreadMatrix);  

    $unreadMatrix = remove_right_column($unreadMatrix); 
    $unreadMatrix = remove_bottom_row($unreadMatrix);   
    $unreadMatrix = remove_left_column($unreadMatrix);  

    return array('new_source'=>$unreadMatrix, 'read_list'=>$read);
}


function remove_top_row($matrix)
{
    $removedRow = array_shift($matrix);
    return $matrix;
}

function remove_right_column($matrix)
{
    $neededCols = count($matrix[0]) - 1;
    $finalMatrix = array();
    for($i=0; $i<count($matrix); $i++) $finalMatrix[$i] = array_slice($matrix[$i], 0, $neededCols);
    return $finalMatrix;
}

function remove_bottom_row($matrix)
{
    unset($matrix[count($matrix)-1]);
    return $matrix;
}

function remove_left_column($matrix)
{
    $neededCols = count($matrix[0]) - 1;
    $finalMatrix = array();
    for($i=0; $i<count($matrix); $i++) $finalMatrix[$i] = array_slice($matrix[$i], 1, $neededCols);
    return $finalMatrix;
}

// Program to print a matrix in spiral order

#include <stdio.h>
int main(void) {
    // your code goes here
    int m,n,i,j,k=1,c1,c2,r1,r2;;
    scanf("%d %d",&m,&n);
    int a[m][n];
    for(i=0;i<m;i++)
    {
        for(j=0;j<n;j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
    r1=0;
    r2=m-1;
    c1=0;
    c2=n-1;

    while(k<=m*n)
                {
                    for(i=c1;i<=c2;i++)
                    {
                        k++;
                        printf("%d ",a[r1][i]);
                    }

                    for(j=r1+1;j<=r2;j++)
                    {
                        k++;
                        printf("%d ",a[j][c2]);
                    }

                    for(i=c2-1;i>=c1;i--)
                    {
                        k++;
                        printf("%d ",a[r2][i]);
                    }

                    for(j=r2-1;j>=r1+1;j--)
                    {
                        k++;
                        printf("%d ",a[j][c1]);
                    }

                 c1++;
                 c2--;
                 r1++;
                 r2--;
                }
    return 0;
}

이것은 모든 mxn 매트릭스에 대한 Java 구현입니다. 행 = 행 수, 열 = 열 수

public static void printSpiral(int rows, int columns, int a[][])
    {
        int i, k = 0, l = 0;

        /*  k - starting row index
            l - starting column index
        */

        while (k < rows && l < columns)
        {
            /* Print the first row from the remaining rows */
            for (i = l; i < columns; ++i)
            {
                System.out.println(a[k][i]);
            }
            k++;

            /* Print the last column from the remaining columns */
            for (i = k; i < rows; ++i)
            {
                System.out.println(a[i][columns-1]);
            }
            columns--;

            /* Print the last row from the remaining rows */
            if ( k < rows)
            {
                for (i = columns-1; i >= l; --i)
                {
                    System.out.println(a[rows-1][i]);
                }
                rows--;
            }

            /* Print the first column from the remaining columns */
            if (l < columns)
            {
                for (i = rows-1; i >= k; --i)
                {
                    System.out.println(a[i][l]);
                }
                l++;    
            }        
        }
    }

여기 내 해결책이 있습니다. 내가 틀렸다면 수정하십시오.

class Spiral:

def spiralOrder(self, A):
    result = []
    c = []
    c.append(A[0])
    b = A[1:]
    while len(b) > 0:
        b = self.rotate(b)
        c.append(b[0])
        b = b[1:]
    for item in c:
        for fitem in item:
            print fitem,
            result.append(fitem)
    return result

def rotate(self,a):
    b = []
    l = zip(*a)
    for i in xrange(len(l)-1,-1,-1):
        b.append(list(l[i]))
    return b

if __name__ == '__main__':
  a = [[1, 2, 3,3], [4, 5, 6,6], [7, 8, 9,10]]
  s = Spiral()
s.spiralOrder(a)

참조 URL : https://stackoverflow.com/questions/726756/print-two-dimensional-array-in-spiral-order

반응형