以螺旋顺序打印二维数组

59

我如何以螺旋顺序打印一个5×5的二维数组?

是否有任何公式可以让我按照螺旋顺序打印任何大小的数组?


6
在什么背景下?HTML?WPF?命令行?Matlab?空中写字? - Tom Ritter
也许他正在解决这个Project Euler问题:http://projecteuler.net/index.php?section=problems&id=28 - Chris Upchurch
38个回答

2
给定一个字符矩阵,实现一个方法按照以下顺序打印所有字符:先打印最外层,然后依次打印内层。
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矩阵是方形矩阵

思路:

我们需要按螺旋的方式在四个不同的方向上遍历。当一个螺旋层结束后,我们需要在矩阵内部遍历一次。因此,总共需要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 ] ) ;
  }

}

如果您删除 {},代码将变得更整洁,就像这里:http://www.crazyforcode.com/print-square-matrix-spiral-form/ - Jackson Tale

1

复杂度: 单次遍历 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;
}

1

斜杠顶行 -> 转置 -> 翻转 -> 重复。

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
这是我的解决方案。如果有错误请纠正。
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)

1
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]

1

这是我的实现:

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

我认为你的解决方案在输入matrix={{1}}, M=1, N=1时会失败。在这种情况下,将什么都不会输出。 - wenqiang
@wenqiang 是的,你说得对,我的代码会失败...我应该考虑边角情况... - WonderLi

0

如果要打印二维矩阵,可以将矩阵视为由矩形和/或线条组成,其中较小的矩形适合较大的矩形中。取形成一个矩形的矩阵边界进行打印,从每层的左上角元素开始每次打印;完成这个步骤后,进入下一层较小矩形的内部。如果没有矩形,则应该打印一条横线或竖线。我已经附上了示例矩阵的代码,希望对你有所帮助。

#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

这是适用于任何 m x n 矩阵的 Java 实现。 其中 rows = 行数 和 Column = 列数

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

这似乎是 GFG 代码的副本,用于剥离二维数组。你至少应该更改他们给出的那些愚蠢的变量名,这完全令人困惑。 - Debu Shinobi

0

使用C#编写的工作代码,附带相关测试用例。它适用于任何 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();
        }
    }
}

请注意,已接受的答案并不适用于任何 n x m 矩阵。该代码使用 @codaddict 在已接受的答案中发布的代码移植到 C#。我已更正了递归基本情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接