Comment imprimer un tableau bidimensionnel 5 × 5 dans un ordre spiralé?
Existe-t-il une formule permettant d’imprimer un tableau de toute taille en ordre de spirale?
L'idée est de traiter la matrice comme une série de calques, de calques en haut à droite et de calques en bas à gauche. Pour imprimer la matrice en spirale, nous pouvons éplucher des couches de cette matrice, imprimer la partie pelée et appeler de manière récursive l'impression sur la partie supérieure gauche. La récursivité se termine lorsque nous n'avons plus de couches à imprimer.
Matrice d'entrée:
1 2 3 4
5 6 7 8
9 0 1 2
3 4 5 6
7 8 9 1
Après avoir pelé la couche en haut à droite:
1 2 3 4
8
5 6 7 2
9 0 1 6
3 4 5 1
7 8 9
Après pelage de la couche inférieure gauche de la sous-matrice:
6 7
5 0 1
9 4 5
3
7 8 9
Après avoir retiré la couche supérieure droite de la sous-matrice:
6 7
1
0 5
4
Après pelage de la couche inférieure gauche de la sous-matrice:
0
4
La récursivité se termine.
Fonctions 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");
}
Code 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)))
Je vois que personne n'a utilisé qu'un seul for loop
et sans récursion dans le code, et je souhaite donc contribuer.
L'idée est la suivante:
Imaginez une tortue se tenant au point (0,0), c’est-à-dire le coin supérieur gauche, face à l’est (à droite)
Continue d'avancer et chaque fois qu'il voit un signe, la tortue tourne à droite
Donc, si nous plaçons la tortue au point (0,0) tourné vers la droite et si nous plaçons les signes aux endroits appropriés, la tortue traversera le tableau en spirale.
Maintenant, le problème est: "Où mettre les panneaux?"
Voyons où nous devrions placer les signes (marqués par # et les nombres par O):
Pour une grille qui ressemble à ceci: OOO O OOO O OOO O OOO O Nous mettons les signes comme suit: OOO # # O # O O # # O # OO # Pour une grille qui ressemble à ceci: OO O OO O OO O .OO O Nous mettons les signes comme ceci: OO # # # O O # O # O # Et pour une grille qui ressemble à ceci: OOOOOO O OOOOOO O OOOOOO O OOOOOO O OOOOOO O Nous mettons les signes comme ceci: OOOOOO #. # OOOO # O O # OO # O O O # OOO # O # OOOOO #
Nous pouvons voir que, sauf si le point est dans la partie supérieure gauche, les signes sont des endroits aux points où les distances jusqu'au bord horizontal le plus proche et au bord vertical le plus proche sont identiques, alors que pour la partie supérieure gauche , la distance par rapport au bord supérieur est supérieure de un à la distance par rapport au bord gauche, la priorité étant donnée en haut à droite si le point est centré horizontalement et en haut à gauche si le point est centré verticalement.
Cela peut être facilement réalisé dans une fonction simple, en prenant le minimum de (curRow
et height-1-curRow
), puis le minimum de (curCol
et width-1-curCol
) et en comparant s’ils sont identiques. Mais nous devons tenir compte du cas situé en haut à gauche, c'est-à-dire lorsque le minimum est curRow
et curCol
eux-mêmes. Dans ce cas, nous réduisons la distance verticale en conséquence.
Voici le code 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);
}
Quelles sorties:
1 2 3 4 8 12 16 15 15 14 13 9 5 6 7 11 10 1 2 3 4 8 12 11 10 9 5 6 7
Voici les trois façons intéressantes
La lecture en spirale peut être traitée comme un serpent se dirigeant vers la limite et tournant sur la limite ou sur elle-même (je la trouve élégante et la plus efficace étant une simple boucle de N itérations)
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)
sortie:
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
Une approche récursive consisterait à imprimer la couche externe et à appeler la même fonction pour le rectangle interne, par exemple.
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)
Enfin, voici un petit extrait pour le faire, pas efficace mais amusant :), en gros, il affiche la ligne du haut, fait pivoter un rectangle entier dans le sens contraire des aiguilles d'une montre et le répète
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)
Ce programme fonctionne pour toute matrice 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]);
}
}
}
}
}
}
J'espère que ça aide
J'étais obsédé par ce problème quand j'apprenais Ruby. C'était le mieux que je puisse faire:
def spiral(matrix)
matrix.empty? ? [] : matrix.shift + spiral(matrix.transpose.reverse)
end
Vous pouvez consulter certaines de mes autres solutions en revenant en arrière dans les révisions de ce Gist . En outre, si vous suivez le lien vers lequel j'ai transmis le Gist, vous trouverez d'autres solutions intelligentes. Problème vraiment intéressant qui peut être résolu de plusieurs manières élégantes - en particulier dans Ruby.
Solution 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++;
}
}
};
Restez simple ->
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);
}
}
La matrice N * N à deux dimensions est une matrice carrée
Idée:
Nous devons traverser dans quatre directions différentes pour traverser comme une spirale . Nous devons traverser à l'intérieur de la matrice une fois qu'une couche de spirale est terminée . Donc, au total, nous avons besoin de 5 boucles, 4 boucles à parcourir comme une spirale et 1 boucle traverser les couches.
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 ] ) ;
}
}
Avec une matrice de caractères, implémentez une méthode qui affiche tous les caractères dans l'ordre suivant: d'abord le cercle extérieur, puis le suivant et ainsi de suite.
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());
}
Une solution implique les directions droite, gauche, haut, bas et leurs limites correspondantes (indices). Une fois que la première ligne est imprimée et que la direction change (de droite) vers le bas, elle est supprimée en augmentant la limite supérieure. Une fois la dernière colonne imprimée et la direction changée à gauche, elle est supprimée en décrémentant la limite de droite ... Les détails sont visibles dans le code C explicite.
#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);
}
Ceci est ma mise en œuvre:
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++;
}
}
Complexité: Traversée simple
O(n)
Laissez-moi ajouter mon boucle unique réponse avec complexité O(n)
. J'ai observé que pendant les traversées gauche-droite et droite-gauche de la matrice, il y a une augmentation et une diminution respectivement de 1 dans l'index des lignes majeures. De même, pour les traversées supérieure-inférieure et inférieure-supérieure, il y a augmentation et diminution de n_cols
. J'ai donc créé un algorithme pour cela. Par exemple, pour une matrice (3x5) avec entrées, l'index de ligne-majeur de la sortie imprimée est: 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)<-------
Solution de code:
#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;
}
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);
}
}
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]);
}
}
J'ai résolu le problème en Python3. Il passe presque tous les cas Edge.
def spiralOrder(self, matrix):
r = len(matrix)
if r == 0:
return []
c = len(matrix[0])
result = []
x = 0; y = 0
while x< r and y<c:
for i in range(y,c):
result.append(matrix[x][i])
x+=1
for i in range(x,r):
result.append(matrix[i][c-1])
c-=1
if x < r:
for i in range(c-1,y-1,-1):
result.append(matrix[r-1][i])
r -=1
if y <c :
for i in range(r-1,x-1,-1):
result.append(matrix[i][y])
y+=1
return result
Cette question est liée à celle-ci: Problèmes d’arrangement matriciel en php
Les réponses présentées semblent fonctionner mais sont compliquées à comprendre. Un moyen très simple de résoudre ce problème est de diviser pour régner, c’est-à-dire qu’après la lecture de l’Edge, supprimez-le et la lecture suivante sera beaucoup plus simple. Découvrez une solution complète dans PHP ci-dessous:
#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;
}
function spiral(a) {
var s = [];
while (a.length) {
// concat 1st row, Push last cols, rotate 180 (reverse inner/outer)...
s = s.concat(a.shift());
a = a
.map(function(v) {
s.Push(v.pop());
return v.reverse();
})
.reverse();
}
return s;
}
var arr = [
[1, 2, 3, 4],
[12, 13, 14, 5],
[11, 16, 15, 6],
[10, 9, 8, 7]
];
console.log(spiral(arr));// -> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
arr = [
[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]
];
console.log(spiral(arr));// -> [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]
C'est une version récursive en C à laquelle je pourrais penser: -
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);
}
Voici ma solution. S'il vous plaît corriger si je me trompe.
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 __== '__main__':
a = [[1, 2, 3,3], [4, 5, 6,6], [7, 8, 9,10]]
s = Spiral()
s.spiralOrder(a)
Pour imprimer une matrice à deux dimensions, considérez la matrice comme une composition de rectangles et/ou de lignes dans laquelle un rectangle plus petit est ajusté dans un plus grand. ; Une fois cela fait, allez à l'intérieur pour la couche suivante d'un rectangle plus petit, au cas où je n'aurais pas de rectangle, il devrait alors être une ligne à imprimer, horizontale ou verticale. J'ai collé le code avec un exemple de matrice, 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]);
}
Vous pouvez imaginer que la spirale consiste en un ensemble ordonné de segments horizontaux et verticaux. Vous pouvez également observer que chaque segment horizontal suivant est un élément plus court que le segment horizontal précédent et chaque segment vertical suivant est un élément plus court que le segment vertical précédent . Chaque segment suivant commence dans une cellule adjacente à la cellule où se termine le segment précédent . Je suppose que nous construisons une spirale dans le sens des aiguilles d'une montre. La longueur du premier segment horizontal est égale à un nombre de colonnes dans une matrice donnée. La longueur du premier segment vertical est égale à un nombre de lignes dans une matrice donnée moins un. En utilisant ces observations, vous pouvez parcourir n’importe quelle matrice NxM sans aucune mémoire supplémentaire ni récursivité dans le temps d’exécution O(NxM)
:
public static void VisitBySpiral<T>(T[,] matrix, Action<T> onVisit)
{
var spiralWidth = matrix.GetLength(1);
var spiralHeight = matrix.GetLength(0);
var row = 0;
var column = 0;
var step = +1;
while (spiralWidth > 0 && spiralHeight > 0)
{
var horizontalSteps = spiralWidth;
while (horizontalSteps-- > 0)
{
onVisit(matrix[row, column]);
if (horizontalSteps > 0)
{
column += step;
}
}
// Move to the cell where next vertical segment starts.
row += step;
--spiralHeight;
var verticalSteps = spiralHeight;
while (verticalSteps-- > 0)
{
onVisit(matrix[row, column]);
if (verticalSteps > 0)
{
row += step;
}
}
--spiralWidth;
step *= -1;
// Move to the cell where next horizontal segment starts.
column += step;
}
}
Ceci est une implémentation Java pour toute matrice m x n. Où rows = Nombre de lignes Et Column = Nombre de colonnes
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++;
}
}
}
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;
}
}
Voici mon approche en utilisant un itérateur. Notez que ceci résout presque le même problème .. Code complet ici: 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();
}
}
}
Code Java si quelqu'un est intéressé.
Contribution :
4
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 7
Sortie : 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);
}
}
}
http://www.technicalinterviewquestions.net/2009/03/print-2d-array-matrix-spiral-order.html
voici la meilleure explication pour la réponse ci-dessus :) ainsi que le diagramme :)
Code de travail en C # avec les cas de test pertinents. Cela fonctionne pour toute matrice n x m
.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MatrixSpiralPrint
{
class Matrix
{
int[,] mat;
public Matrix(int[,] matrix)
{
mat = matrix;
}
void printHelper(int x)
{
Console.Write(string.Format("{0} ", x));
}
// print the top right of the matrix and
// recursively call the print bottom left on the submatrix.
void printTopRight(int colStart, int rowStart, int colEnd, int rowEnd)
{
int i = 0, j = 0;
// print Top row.
for (i = colStart; i <= colEnd; i++)
{
printHelper(mat[rowStart, i]);
}
// print Right column.
for (j = rowStart + 1; j <= rowEnd; j++)
{
printHelper(mat[j, colEnd]);
}
// Recursion base case: see if more layers need to be printed.
if (colEnd - colStart > 0 && rowStart!=rowEnd)
{
// print the bottom left of the sub matrix.
printBottomLeft(colStart, rowStart + 1, colEnd - 1, rowEnd);
}
}
// print the bottom left peel of the matrix and
// recursively call the print top right on the submatrix.
void printBottomLeft(int colStart, int rowStart, int colEnd, int rowEnd)
{
int i = 0, j = 0;
// print Bottom row in reverse order.
for (i = colEnd; i >= colStart; i--)
{
printHelper(mat[rowEnd, i]);
}
// print Left column in reverse order.
for (j = rowEnd - 1; j >= rowStart; j--)
{
printHelper(mat[j, colStart]);
}
// Recursion base case: see if more layers need to be printed.
if (colEnd - colStart > 0)
{
// print the top right of the sub matrix.
printTopRight(colStart + 1, rowStart, colEnd, rowEnd - 1);
}
}
void printMatrix()
{
int rowLength = mat.GetLength(0);
int colLength = mat.GetLength(1);
Console.WriteLine("Test Case");
for (int i = 0; i < rowLength; i++)
{
for (int j = 0; j < colLength; j++)
{
Console.Write(string.Format("{0} ", mat[i, j]));
}
Console.Write(Environment.NewLine + Environment.NewLine);
}
}
public void printSpiral()
{
var maxRowIndex = mat.GetUpperBound(0);
var maxColIndex = mat.GetUpperBound(1);
printMatrix();
Console.WriteLine("Spiral Print");
printTopRight(0, 0, maxColIndex, maxRowIndex);
Console.WriteLine("\n---------------------------------");
}
}
class Program
{
static void Main(string[] args)
{
var matrix = new int[,] {
{ 1,2,3,4,5},
{ 6,7,8,9,10},
{ 11,12,13,14,15},
{ 16,17,18,19,20},
{ 21,22,23,24,25}
};
var mat = new Matrix(matrix);
mat.printSpiral();
matrix = new int[,] {
{ 1,2,3,4},
{ 5,6,7,8},
{ 9,10,11,12}
};
mat = new Matrix(matrix);
mat.printSpiral();
matrix = new int[,] {
{ 1,2,3},
{ 4,5,6},
{ 7,8,9},
{ 10,11,12},
};
mat = new Matrix(matrix);
mat.printSpiral();
matrix = new int[,] {
{ 1,2 }
};
mat = new Matrix(matrix);
mat.printSpiral();
matrix = new int[,] {
{ 1},
{ 2}
};
mat = new Matrix(matrix);
mat.printSpiral();
}
}
}
Notez que la réponse acceptée ne fonctionne avec aucune matrice n x m
. Ce code est porté en C # à l'aide du code envoyé par @codaddict dans la réponse acceptée. J'ai corrigé le cas de base de récursivité.
Voici ma solution en 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();
}
}
Voici mon implémentation en 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);
}
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--;
}
}
// 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;
}
#include <iostream>
using namespace std;
const int MAX=100;
int main(void)
{
int a[MAX][MAX],i,j,lower,upper,k,n=0,am=0;
cout<<"enter number or size of matrix \n"<<endl;
cin>>n;
// assigning the value
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
a[i][j]=am+1;
}
i=0;
j=0;
lower=0,upper=n-1;
for(k=0;k<(n*n);k++)
{
cout<<a[i][j]<<"\t";
if((i==lower)&&(j<upper))
j++;
else if((j==upper)&&(i<lower))
j--;
else if((j==lower)&&(i>lower))
i--;
if((a[i][j]==a[lower][i]))
{
lower++;
upper--;
i++;
j++;
}
}
return 0;
}
Programme C complet complet pour toute matrice de tableau 2D avec rangée x colonne .
#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;
}