如何以螺旋顺序打印5×5二维数组?
是否有任何公式,以便我可以按螺旋顺序打印任何大小的数组?
答案 0 :(得分:77)
我们的想法是将矩阵视为一系列图层,右上图层和左下图层。为了以螺旋方式打印基质,我们可以从这些基质上剥离层,打印去皮部分并递归调用左侧部分的打印件。当我们没有任何要打印的图层时,递归终止。
输入矩阵:
1 2 3 4
5 6 7 8
9 0 1 2
3 4 5 6
7 8 9 1
剥离右上层后:
1 2 3 4
8
5 6 7 2
9 0 1 6
3 4 5 1
7 8 9
从子矩阵剥离左下图层后
6 7
5 0 1
9 4 5
3
7 8 9
从子矩阵剥离右上层后:
6 7
1
0 5
4
从子矩阵剥离左下图层后
0
4
递归终止。
C函数:
// function to print the top-right peel of the matrix and
// recursively call the print bottom-left on the submatrix.
void printTopRight(int a[][COL], int x1, int y1, int x2, int y2) {
int i = 0, j = 0;
// print values in the row.
for(i = x1; i<=x2; i++) {
printf("%d ", a[y1][i]);
}
// print values in the column.
for(j = y1 + 1; j <= y2; j++) {
printf("%d ", a[j][x2]);
}
// see if more layers need to be printed.
if(x2-x1 > 0) {
// if yes recursively call the function to
// print the bottom left of the sub matrix.
printBottomLeft(a, x1, y1 + 1, x2-1, y2);
}
}
// function to print the bottom-left peel of the matrix and
// recursively call the print top-right on the submatrix.
void printBottomLeft(int a[][COL], int x1, int y1, int x2, int y2) {
int i = 0, j = 0;
// print the values in the row in reverse order.
for(i = x2; i>=x1; i--) {
printf("%d ", a[y2][i]);
}
// print the values in the col in reverse order.
for(j = y2 - 1; j >= y1; j--) {
printf("%d ", a[j][x1]);
}
// see if more layers need to be printed.
if(x2-x1 > 0) {
// if yes recursively call the function to
// print the top right of the sub matrix.
printTopRight(a, x1+1, y1, x2, y2-1);
}
}
void printSpiral(int arr[][COL]) {
printTopRight(arr,0,0,COL-1,ROW-1);
printf("\n");
}
答案 1 :(得分:31)
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)))
答案 2 :(得分:23)
我发现没有人在代码中使用只有一个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 #
我们可以看到,除非该点位于左上角,否则符号位于到最近的水平边界的距离和最近的垂直边界相同的点,而对于左上角部分,到顶部边框的距离比离开左边框的距离多一个,如果点水平居中,则优先考虑右上角,并且如果该点垂直居中,则留下。
这可以通过一个简单的函数很容易地实现,采用(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
答案 3 :(得分:8)
以下是三种有趣的方式
以螺旋方式阅读可以被视为一条蛇向边界移动并打开边界或自身(我发现它优雅且最有效的是N次迭代的单循环)
ar = [
[ 0, 1, 2, 3, 4],
[15, 16, 17, 18, 5],
[14, 23, 24, 19, 6],
[13, 22, 21, 20, 7],
[12, 11, 10, 9, 8]]
def print_spiral(ar):
"""
assuming a rect array
"""
rows, cols = len(ar), len(ar[0])
r, c = 0, -1 # start here
nextturn = stepsx = cols # move so many steps
stepsy = rows-1
inc_c, inc_r = 1, 0 # at each step move this much
turns = 0 # how many times our snake had turned
for i in range(rows*cols):
c += inc_c
r += inc_r
print ar[r][c],
if i == nextturn-1:
turns += 1
# at each turn reduce how many steps we go next
if turns%2==0:
nextturn += stepsx
stepsy -= 1
else:
nextturn += stepsy
stepsx -= 1
# change directions
inc_c, inc_r = -inc_r, inc_c
print_spiral(ar)
输出:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
递归方法是打印外层并为内部矩形调用相同的函数,例如
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)
答案 4 :(得分:6)
此程序适用于任何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]);
}
}
}
}
}
}
希望有所帮助
答案 5 :(得分:5)
当我学习Ruby时,我对这个问题很着迷。这是我能做的最好的事情:
def spiral(matrix)
matrix.empty? ? [] : matrix.shift + spiral(matrix.transpose.reverse)
end
您可以通过退回此gist中的修订版来查看我的其他一些解决方案。此外,如果你按照我分享要点的链接回来,你会找到一些其他聪明的解决方案。非常有趣的问题,可以通过多种优雅的方式解决 - 尤其是在Ruby中。
答案 6 :(得分:3)
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++;
}
}
};
答案 7 :(得分:2)
Two dimensional N*N Matrix is Square matrix
想法:
我们必须在四个不同的方向上穿过像螺旋一样的横穿。 一旦螺旋层结束,我们必须遍历矩阵内部。 总而言之,我们需要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 ] ) ;
}
}
答案 8 :(得分:2)
保持简单 - &gt;
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);
}
}
答案 9 :(得分: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());
}
答案 10 :(得分:2)
一种解决方案涉及方向右,左,上,下及其相应的限制(指数)。一旦打印出第一行,并且方向改变(从右)到下行,则通过递增上限来丢弃该行。打印完最后一列后,方向更改为左侧,通过递减右侧限制来丢弃该列...详细信息可以在不言自明的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);
}
答案 11 :(得分:1)
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]);
}
}
答案 12 :(得分: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++;
}
}
答案 13 :(得分:1)
复杂性:单遍历
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;
}
答案 14 :(得分: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);
}
}
答案 15 :(得分: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#。我纠正了递归基础案例。
答案 16 :(得分:0)
这是任何m x n矩阵的java实现。 其中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++;
}
}
}
答案 17 :(得分:0)
这是我的解决方案。如果我错了,请更正。
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)
答案 18 :(得分:0)
// 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;
}
答案 19 :(得分: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;
}
答案 20 :(得分:0)
您可以想象螺旋由一组有序的水平和垂直线段组成。您还可以观察到每个下一个水平线段比前一个水平线段短一个元素,每个下一个垂直线段比前一个垂直线段短一个元素。每个下一个片段都在与前一个片段结束的单元格相邻的单元格中开始。我假设我们沿顺时针方向构造螺旋。第一个水平段长度等于给定矩阵中的列数。第一垂直段长度等于给定矩阵中的行数减1。使用这些观察结果,您可以在O(NxM)
运行时间内遍历任何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;
}
}
答案 21 :(得分:0)
这是我在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();
}
}
答案 22 :(得分:0)
我已经解决了Python3中的问题。几乎所有边缘情况都通过了。
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
答案 23 :(得分:0)
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]
答案 24 :(得分:0)
这是C ++中很好的递归解决方案,
#include <iostream>
#include <vector>
using namespace std;
void helper(const vector<vector<int>>& arr, vector<int>& spiral, int i, int j, int until, int i_, int j_) {
int& comp = j_ != 0 ? j : i;
while(until != comp) {
spiral.push_back(arr.at(i).at(j));
i += i_;
j += j_;
}
}
void get_spiral_ordering(vector<int>& spiral, const vector<vector<int>>& arr, int i, int until) {
if(until == i) {
spiral.push_back(arr.at(i).at(i));
return;
} else if(until < i) return;
helper(arr, spiral, i, i, until, 0, 1);
helper(arr, spiral, i, until, until, 1, 0);
helper(arr, spiral, until, until, arr.size()-1-until, 0, -1);
helper(arr, spiral, until, i, arr.size()-1-until, -1, 0);
return get_spiral_ordering(spiral, arr, i+1, until-1);
}
要使用此代码,对于任何nxn维数组以获取其螺旋顺序,请调用get_spiral_ordering(result_vec, src, 0, src.size()-1)
答案 25 :(得分:0)
这个问题与此问题有关:Matrix arrangement issues in 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;
}
答案 26 :(得分:0)
使用给定行x列的任何二维阵列矩阵完成纯C程序。
#include <stdio.h>
void printspiral(int *p,int r, int c) {
int i=0,j=0,m=1,n=0;
static int firstrun=1,gCol;
if (!p||r<=0||c<=0)
return ;
if(firstrun) {
gCol=c;
firstrun=0;
}
for(i=0,j=0;(0<=i && i<c)&&(0<=j && j<r);i+=m,j+=n) {
printf(" %d",p[i+j*gCol]);
if (i==0 && j==1 && (i+1)!=c) break;
else if (i+1==c && !j) {m=0;n=1;}
else if (i+1==c && j+1==r && j) {n=0;m=-1;}
else if (i==0 && j+1==r && j) {m=0;n=-1;}
}
printspiral(&p[i+j*gCol+1],r-2,c-2);
firstrun=1;
printf("\n");
}
int main() {
int a[3][3]={{0,1,2},{3,4,5},{6,7,8}};
int b[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
int c[4][3]={{0,1,2},{3,4,5},{6,7,8},{9,10,11}};
int d[3][1]={{0},{1},{2}};
int e[1][3]={{0,1,2}};
int f[1][1]={{0}};
int g[5][5]={{0,1,2,3,4},{5,6,7,8,9},{10,11,12,13,14},{15,16,17,18,19},{20,21,22,23,24}};
printspiral(a,3,3);
printspiral(b,3,4);
printspiral(c,4,3);
printspiral(d,3,1);
printspiral(e,1,3);
printspiral(f,1,1);
printspiral(g,5,5);
return 0;
}
答案 27 :(得分:0)
这是我使用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();
}
}
}
答案 28 :(得分:0)
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;
}
}
答案 29 :(得分:0)
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--;
}
}
答案 30 :(得分:0)
http://www.technicalinterviewquestions.net/2009/03/print-2d-array-matrix-spiral-order.html
以上是对上述答案的最佳解释:)以及图表:)
答案 31 :(得分:0)
这是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);
}
答案 32 :(得分:0)
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);
}
}
}
答案 33 :(得分:0)
//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);
}
答案 34 :(得分:0)
这是我在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*/
}
}
答案 35 :(得分:0)
对于打印二维矩阵,将矩阵视为矩形和/或线的组合,其中较小的矩形拟合为较大的矩形,取矩阵的边界,形成要打印的矩形,每次从左上角开始在每一层;一旦完成这个进入下一层较小的矩形,如果我没有一个矩形,那么它应该是打印的行,水平或垂直。我用代码矩阵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]);
}
答案 36 :(得分:-1)
/// <param name="arr"></param>
/// <param name="w">CONSTANT width</param>
/// <param name="h">CONSTANT height of array</param>
/// <param name="i">index or 1d array. At start is 0</param>
/// <param name="n">number of printed elements. At start is 0</param>
/// <param name="l">spiral loop. At start is 0</param>
/// <param name="d">direction of iteration. At start is 1</param>
/// <returns></returns>
private int print(Array arr, int w, int h, int i, int n, int l, byte direction)
{
int x = i % w;
int y = (i - x) / w;
Console.Write(arr.GetValue(i) + " ");
n++;
if (n == arr.Length) return 0;
switch (direction)
{
case 1://→
if (x < w - l - 1)
{
return print(arr, w, h, i + 1, n, l, 1);
}
return print(arr, w, h, i + w, n, l, 2);
case 2://↓
if (y < h - l - 1)
{
return print(arr, w, h, i + w, n, l, 2);
}
return print(arr, w, h, i - 1, n, l, 3);
case 3://←
if (x > l)
{
return print(arr, w, h, i - 1, n, l, 3);
}
return print(arr, w, h, i - w, n, l, 4);
case 4://↑
if (y > l + 1)
{
return print(arr, w, h, i - w, n, l, 4);
}
return print(arr, w, h, i + 1, n, l + 1, 1);
default:
return 0;
}
}