Сгладить двухмерный массив, идущий по часовой стрелке [дубликат]

Другим сценарием является то, что вы нанесли нулевой объект в тип значения . Например, код ниже:

object o = null;
DateTime d = (DateTime)o;

Он выкинет NullReferenceException в роли. В приведенном выше примере это кажется совершенно очевидным, но это может произойти в более «поздних связующих» сложных сценариях, где нулевой объект был возвращен из некоторого кода, которого вы не являетесь, и приведение, например, генерируется некоторой автоматической системой.

Одним из примеров этого является этот простой фрагмент привязки ASP.NET с элементом управления календарем:

" />

Здесь SelectedDate на самом деле является свойством - типа DateTime - типа Calendar Web Control, и привязка может отлично вернуть что-то null. Неявный генератор ASP.NET создаст кусок кода, который будет эквивалентен приведенному выше методу. И это поднимет NullReferenceException, что довольно сложно определить, потому что он лежит в сгенерированном ASP.NET коде, который компилирует отлично ...

50
задан codaddict 16 February 2011 в 05:49
поделиться

30 ответов

Идея состоит в том, чтобы рассматривать матрицу как серию слоев, верхних правых слоев и нижних левых слоев. Чтобы напечатать матрицу по спирали, мы можем очистить слои от этой матрицы, напечатать очищенную часть и рекурсивно вызвать печать слева над частью. Рекурсия завершается, когда у нас больше нет слоев для печати. ​​

Входная матрица:

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

Идеальная ссылка

73
ответ дан Adriano 26 August 2018 в 14:28
поделиться
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--;
    }

}
0
ответ дан Akhilesh Dhar Dubey 26 August 2018 в 14:28
поделиться

Это реализация java для любой матрицы m x n. Где rows = Число строк и Столбец = Число столбцов

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++;    
            }        
        }
    }
0
ответ дан anand mishra 26 August 2018 в 14:28
поделиться

Вот три интересных способа

  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)
    

output:

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)
7
ответ дан Anurag Uniyal 26 August 2018 в 14:28
поделиться

Одно решение включает в себя направления справа, слева, вверх, вниз и соответствующие им пределы (индексы). После печати первой строки и изменения направления (справа) вниз, строка отбрасывается путем увеличения верхнего предела. После того, как последний столбец будет напечатан, а направление изменится влево, столбец будет отброшен путем уменьшения предела правой руки ... Детали можно увидеть в понятном 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);
}

Ссылка для тестирования и загрузки .

2
ответ дан Apshir 26 August 2018 в 14:28
поделиться
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;
    }
}
0
ответ дан atjoshi 26 August 2018 в 14:28
поделиться

Завершить чистую программу C для любой матрицы 2D-массива с заданной строкой x column .

#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;                                                                                                                           
}
0
ответ дан Balamurugan A 26 August 2018 в 14:28
поделиться

Вот моя реализация в 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*/ 

    }

}
0
ответ дан bantini 26 August 2018 в 14:28
поделиться

Двумерная матрица N * N является квадратной матрицей

Идея:

Мы должны проходить в четырех разных направлениях, чтобы пересечь как спираль. Мы должны пересечь внутреннюю матрицу после того, как закончится один слой спирали. Итак, всего, нам нужно 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 ] ) ;
  }

}
2
ответ дан Billz 26 August 2018 в 14:28
поделиться

Для печати двумерной матрицы рассмотрим матрицу как композицию прямоугольников и / или линии, в которой меньший прямоугольник установлен в большую, возьмите границу матрицы, которая образует прямоугольник, который будет печататься, начиная с левого верхнего элемента каждый раз в каждом слое; как только вы сделаете это, перейдите внутрь для следующего слоя меньшего прямоугольника, в случае, если у меня нет прямоугольника, тогда это должна быть строка для печати, горизонтальная или вертикальная. Я вставил код с примерной матрицей 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]);

}
0
ответ дан Cleonjoys 26 August 2018 в 14:28
поделиться

Этот вопрос связан с этим: Проблемы с расположением матриц в 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;
}
30
ответ дан Community 26 August 2018 в 14:28
поделиться

Сложность: одиночный траверс O(n)

Пожалуйста, позвольте мне добавить мой единственный цикл ответа со сложностью O(n). Я заметил, что во время левого и правого левого перемещения матрицы происходит увеличение и уменьшение на единицу соответственно в индексе строки. Точно так же для верхнего и нижнего верха ход увеличивается и уменьшается на 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;
}
1
ответ дан Darkmoor 26 August 2018 в 14:28
поделиться

Я вижу, что никто не использует только один for loop и без рекурсии в коде, и поэтому я хочу внести свой вклад.

Идея такова:

Представьте себе, что в точке (0,0) находится черепаха, то есть левый верхний угол, обращенный к востоку (вправо)

Он будет продолжать движение вперед и каждый раз, когда он увидит знак , черепаха повернуть направо

Итак, если мы поместим черепаху в точку (0,0), обращенную вправо, и если мы поместим знаки в соответствующие места, черепаха будет проходить по спирали .

Теперь проблема заключается в следующем: «Куда поместить знаки?»

Давайте посмотрим, где мы должны поместить знаки (отмеченные символом # и номерами на O) :

For a grid that looks like this:
O O O O
O O O O
O O O O
O O O O

We put the signs like this:
O O O #
# O # O
O # # O
# O O #

For a grid that looks like this:
O O O
O O O
O O O
O O O

We put the signs like this:
O O #
# # O
O # O
# O #

And for a grid that looks like this:
O O O O O O O
O O O O O O O
O O O O O O O
O O O O O O O
O O O O O O O

We put the signs like this:
O O O O O O #
# O O O O # O
O # O O # O O
O # O O O # O
# O O O O O #

Мы видим, что, если точка не находится в верхней левой части, знаки являются точками в точках, где расстояния до ближайшей горизонтальной границы и ближайшей вертикальной границы одинаковы, в то время как для верхней левой части расстояние до верхней границы больше, чем расстояние до левой границы, априори [7]

Это может быть реализовано простой функцией довольно легко, взяв минимум из-за того, что точка находится в верхнем правом углу, если точка горизонтально центрирована, а вверху слева. (curRow и height-1-curRow), то минимум (curCol и width-1-curCol) и сравните, если они одинаковы. Но нам нужно учитывать верхний левый случай, т. Е. Когда минимум равен curRow и curCol. В этом случае мы соответственно уменьшаем вертикальное расстояние.

Вот код 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);
}

Какие выходы:

1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10
1 2 3 4 8 12 11 10 9 5 6 7
23
ответ дан justhalf 26 August 2018 в 14:28
поделиться

Вот мое решение. Пожалуйста, исправьте, если я ошибаюсь.

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)
0
ответ дан ketan 26 August 2018 в 14:28
поделиться

Эта программа работает для любой 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]);
                    }
                }
            }
        }
    }
}

Надеюсь, что это поможет

6
ответ дан madth3 26 August 2018 в 14:28
поделиться

Вот мое решение в 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();
    }
}
0
ответ дан MattMacdonald 26 August 2018 в 14:28
поделиться

Если задана матрица символов, реализуйте метод, который печатает все символы в следующем порядке: сначала внешний круг, затем следующий и т. д.

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
ответ дан Maya Raveh 26 August 2018 в 14:28
поделиться

Я был одержим этой проблемой, когда я изучал Руби. Это было лучшее, что я мог сделать:

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

Вы можете проверить некоторые из моих других решений, отступив через ревизии в этом gist . Кроме того, если вы перейдете по ссылке, к которой я разветвлял суть, вы найдете некоторые другие умные решения. Действительно интересная проблема, которая может быть решена несколькими элегантными способами - особенно в Ruby.

4
ответ дан O-I 26 August 2018 в 14:28
поделиться

Просто сохраните это просто ->

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

}

1
ответ дан piyush121 26 August 2018 в 14:28
поделиться

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

вот лучшее объяснение для вышеупомянутый ответ :) вместе с диаграммой:)

0
ответ дан Priyanka 26 August 2018 в 14:28
поделиться

Вот мой подход с использованием 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();
        }
    }
}
0
ответ дан RD. 26 August 2018 в 14:28
поделиться

Java-код, если кому-то интересно. Вход: 4 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 Выход: 1 2 3 4 8 3 7 6 5 4 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);
    }
  }
}
0
ответ дан sadakurapati 26 August 2018 в 14:28
поделиться
//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);
}
0
ответ дан Shivendra 26 August 2018 в 14:28
поделиться

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);
    }
}
1
ответ дан Sorter 26 August 2018 в 14:28
поделиться

Решение для JavaScript:

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++;
    }
  }
};
3
ответ дан spark 26 August 2018 в 14:28
поделиться

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

}

1
ответ дан Stupid Aneesh eating chipz 26 August 2018 в 14:28
поделиться
// 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;
}
0
ответ дан user3719609 26 August 2018 в 14:28
поделиться

Это рекурсивная версия в 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);

 }
0
ответ дан whizvids 26 August 2018 в 14:28
поделиться

Это моя реализация:

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++;
    }
}
1
ответ дан WonderLi 26 August 2018 в 14:28
поделиться
  1. Pop top row
  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)))
30
ответ дан Community 26 August 2018 в 14:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: