Другим сценарием является то, что вы нанесли нулевой объект в тип значения . Например, код ниже:
object o = null;
DateTime d = (DateTime)o;
Он выкинет NullReferenceException
в роли. В приведенном выше примере это кажется совершенно очевидным, но это может произойти в более «поздних связующих» сложных сценариях, где нулевой объект был возвращен из некоторого кода, которого вы не являетесь, и приведение, например, генерируется некоторой автоматической системой.
Одним из примеров этого является этот простой фрагмент привязки ASP.NET с элементом управления календарем:
" />
Здесь SelectedDate
на самом деле является свойством - типа DateTime
- типа Calendar
Web Control, и привязка может отлично вернуть что-то null. Неявный генератор ASP.NET создаст кусок кода, который будет эквивалентен приведенному выше методу. И это поднимет NullReferenceException
, что довольно сложно определить, потому что он лежит в сгенерированном ASP.NET коде, который компилирует отлично ...
Идея состоит в том, чтобы рассматривать матрицу как серию слоев, верхних правых слоев и нижних левых слоев. Чтобы напечатать матрицу по спирали, мы можем очистить слои от этой матрицы, напечатать очищенную часть и рекурсивно вызвать печать слева над частью. Рекурсия завершается, когда у нас больше нет слоев для печати.
Входная матрица:
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");
}
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--;
}
}
Это реализация 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++;
}
}
}
Вот три интересных способа
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
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)
Одно решение включает в себя направления справа, слева, вверх, вниз и соответствующие им пределы (индексы). После печати первой строки и изменения направления (справа) вниз, строка отбрасывается путем увеличения верхнего предела. После того, как последний столбец будет напечатан, а направление изменится влево, столбец будет отброшен путем уменьшения предела правой руки ... Детали можно увидеть в понятном C-коде.
#include <stdio.h>
#define N_ROWS 5
#define N_COLS 3
void print_spiral(int a[N_ROWS][N_COLS])
{
enum {up, down, left, right} direction = right;
int up_limit = 0,
down_limit = N_ROWS - 1,
left_limit = 0,
right_limit = N_COLS - 1,
downcount = N_ROWS * N_COLS,
row = 0,
col = 0;
while(printf("%d ", a[row][col]) && --downcount)
if(direction == right)
{
if(++col > right_limit)
{
--col;
direction = down;
++up_limit;
++row;
}
}
else if(direction == down)
{
if(++row > down_limit)
{
--row;
direction = left;
--right_limit;
--col;
}
}
else if(direction == left)
{
if(--col < left_limit)
{
++col;
direction = up;
--down_limit;
--row;
}
}
else /* direction == up */
if(--row < up_limit)
{
++row;
direction = right;
++left_limit;
++col;
}
}
void main()
{
int a[N_ROWS][N_COLS] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
print_spiral(a);
}
public class SpiralPrint{
//print the elements of matrix in the spiral order.
//my idea is to use recursive, for each outer loop
public static void printSpiral(int[][] mat, int layer){
int up = layer;
int buttom = mat.length - layer - 1;
int left = layer;
int right = mat[0].length - layer - 1;
if(up > buttom+1 || left > right + 1)
return; // termination condition
//traverse the other frame,
//print up
for(int i = left; i <= right; i ++){
System.out.print( mat[up][i]+ " " );
}
//print right
for(int i = up + 1; i <=buttom; i ++){
System.out.print(mat[i][right] + " ");
}
//print buttom
for(int i = right - 1; i >= left; i --){
System.out.print(mat[buttom][i] + " ");
}
//print left
for(int i = buttom - 1; i > up; i --){
System.out.print(mat[i][left] + " ");
}
//recursive call for the next level
printSpiral(mat, layer + 1);
}
public static void main(String[] args){
int[][] mat = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}, {13,14,15,16}};
int[][] mat2 = {{1,2,3}, {4,5,6}, {7,8,9}, {10,11,12}};
SpiralPrint.printSpiral(mat2,0);
return;
}
}
Завершить чистую программу C для любой матрицы 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;
}
Вот моя реализация в 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*/
}
}
Двумерная матрица 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 ] ) ;
}
}
Для печати двумерной матрицы рассмотрим матрицу как композицию прямоугольников и / или линии, в которой меньший прямоугольник установлен в большую, возьмите границу матрицы, которая образует прямоугольник, который будет печататься, начиная с левого верхнего элемента каждый раз в каждом слое; как только вы сделаете это, перейдите внутрь для следующего слоя меньшего прямоугольника, в случае, если у меня нет прямоугольника, тогда это должна быть строка для печати, горизонтальная или вертикальная. Я вставил код с примерной матрицей 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]);
}
Этот вопрос связан с этим: Проблемы с расположением матриц в 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;
}
Сложность: одиночный траверс
blockquote>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; }
Я вижу, что никто не использует только один for loop
и без рекурсии в коде, и поэтому я хочу внести свой вклад.
Идея такова:
Представьте себе, что в точке (0,0) находится черепаха, то есть левый верхний угол, обращенный к востоку (вправо)
Он будет продолжать движение вперед и каждый раз, когда он увидит знак , черепаха повернуть направо
Итак, если мы поместим черепаху в точку (0,0), обращенную вправо, и если мы поместим знаки в соответствующие места, черепаха будет проходить по спирали .
Теперь проблема заключается в следующем: «Куда поместить знаки?»
blockquote>Давайте посмотрим, где мы должны поместить знаки (отмеченные символом # и номерами на 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
Вот мое решение. Пожалуйста, исправьте, если я ошибаюсь.
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)
Эта программа работает для любой 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]);
}
}
}
}
}
}
Надеюсь, что это поможет
Вот мое решение в 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();
}
}
Если задана матрица символов, реализуйте метод, который печатает все символы в следующем порядке: сначала внешний круг, затем следующий и т. д.
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());
}
Я был одержим этой проблемой, когда я изучал Руби. Это было лучшее, что я мог сделать:
def spiral(matrix)
matrix.empty? ? [] : matrix.shift + spiral(matrix.transpose.reverse)
end
Вы можете проверить некоторые из моих других решений, отступив через ревизии в этом gist . Кроме того, если вы перейдете по ссылке, к которой я разветвлял суть, вы найдете некоторые другие умные решения. Действительно интересная проблема, которая может быть решена несколькими элегантными способами - особенно в Ruby.
Просто сохраните это просто ->
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);
}
}
http://www.technicalinterviewquestions.net/2009/03/print-2d-array-matrix-spiral-order.html
вот лучшее объяснение для вышеупомянутый ответ :) вместе с диаграммой:)
Вот мой подход с использованием 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();
}
}
}
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);
}
}
}
//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);
}
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);
}
}
Решение для 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++;
}
}
};
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]);
}
}
// 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;
}
Это рекурсивная версия в 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);
}
Это моя реализация:
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++;
}
}
Код 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)))