首页 > 试题广场 >

螺旋数

[编程题]螺旋数
  • 热度指数:587 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
下图是一个4阶的螺旋数阵:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
数字从1开始,沿着顺时针方向依次填满整个矩阵。
现在给你矩阵的规模n,请你输出n阶螺旋数阵。

输入描述:
输入包含多组数据,每组数据包含一个正整数n(1≤n≤20)。


输出描述:
对应每组数据,输出相应的螺旋数阵。

每组数据之后输出一个空行作为分隔。
示例1

输入

3
4

输出

1 2 3
8 9 4
7 6 5

1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
用c++写的比较好理解的例子
编辑于 2016-11-14 20:57:05 回复(0)
#include <cstdio>
#include <vector>
using namespace std;
int main()
{
 int n;
 while (scanf("%d", &n) != EOF)
 {
  vector<vector<int>> mat(n, vector<int>(n));
  int num = 1;
  for (int step = 0; step < (n >> 1); ++step)
  {
   for (int j = step; j < n - step; ++j) mat[step][j] = num++;
   for (int i = step + 1; i < n - step; ++i) mat[i][n - 1 - step] = num++;
   for (int j = n - 2 - step; j >= step; --j) mat[n - 1 - step][j] = num++;
   for (int i = n - 2 - step; i > step; --i) mat[i][step] = num++;
  }
  if (n & 1) mat[n >> 1][n >> 1] = num;
  for (int i = 0; i < n; ++i)
  {
   for (int j = 0; j < n - 1; ++j)
    printf("%d ", mat[i][j]);
   printf("%d\n", mat[i][n - 1]);
  }
  printf("\n");
 }
 return 0;
}

发表于 2017-07-26 21:54:08 回复(0)
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
using namespace std;

int main(int argc, char** argv){
	int n;
	while(cin >> n){
		vector<vector<int>> temp(n, vector<int>(n, 0));
		int begin_x = 0, begin_y = 0, end_x = n, end_y = n;
		int dx[4] = {0, 1, 0, -1};
		int dy[4] = {1, 0, -1, 0};
		int flag = 0;
		int x = 0, y = 0;
		int cur = 1;
		while(cur <= n*n){
			if(x >= begin_x && x < end_x && y >= begin_y && y < end_y){
				temp[x][y] = cur;
				cur++;
				x += dx[flag];
				y += dy[flag]; 
			}
			else{
				if(flag == 0) begin_x++;
				else if(flag == 1) end_y--;
				else if(flag == 2) end_x--;
				else if(flag == 3) begin_y++;
				x -= dx[flag];
				y -= dy[flag]; 
				flag++;
				if(flag == 4) flag = 0;
				x += dx[flag];
				y += dy[flag]; 
			}
		}
		for(int i = 0; i < n; i++){
			for(int j = 0; j < n; j++){
				cout << temp[i][j] << " ";
			}
			cout << endl;
		}
		cout << endl;
	}
	return 0;
}

发表于 2019-09-13 20:30:25 回复(0)

需要判断重复写入,重复写入将导致出错

1 . j+1<n判断是否到达边界,因为res[0][0]已经赋值了

  1. i>=1判断是到达边界
    while True:
     try:
         n = int(input())
         res = [[0 for _ in range(n)] for _ in range(n)]
         tot,i,j=1,0,0
         res[0][0] = tot
         while tot<n**2:
             while j+1<n and not res[i][j+1]:
                 tot += 1
                 j+=1
                 res[i][j]=tot
             while i+1<n and not res[i+1][j]:
                 tot += 1
                 i += 1
                 res[i][j]=tot
             while 1<=j and not res[i][j-1]:
                 tot += 1
                 j -= 1
                 res[i][j]=tot
             while i >=1 and not res[i-1][j]:
                 tot += 1
                 i -= 1
                 res[i][j]=tot
         for i in res:
             print(' '.join(map(str,i)))
         print()
     except:break
编辑于 2019-07-18 13:38:52 回复(0)
#include<iostream>
#include<vector>
#include<stdlib.h>
#include<cstring>

using namespace std;
vector <vector <int> > mat,a;

int move(int x,int y,int flag,int line,int row,int k){
    a[x][y]=1;         //表示访问过
   mat[x][y]=k;
    k++;
    switch(flag){
        case 1:    //向右
            if((y<row-1)&&(a[x][y+1]==0))
                move(x,y+1,1,line,row,k);
            else if(a[x+1][y]==0)
                move(x+1,y,2,line,row,k);
            break;
        case 2:   //向下
            if((x<line-1)&&(a[x+1][y]==0))
                move(x+1,y,2,line,row,k);
            else if(a[x][y-1]==0)
                move(x,y-1,-1,line,row,k);
            break;

        case -1:    //向左
            if((y>0)&&(a[x][y-1]==0))
                move(x,y-1,-1,line,row,k);
            else if(a[x-1][y]==0)
                move(x-1,y,3,line,row,k);
            break;
        case 3: //向上
            if((x>0)&&(a[x-1][y]==0))
                move(x-1,y,3,line,row,k);
            else if(a[x][y+1]==0)
                move(x,y+1,1,line,row,k);
            break;
        default:
            break;


    }
    return 0;
}
int main(){
int n,m;
while(cin>>n){
    int k=1;
    mat.resize(n);
    a.resize(n);
    for(int i=0;i<n;i++)
    {
        a[i].resize(n);
        mat[i].resize(n);
    }
    //memset(a,0,sizeof(a));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
           // cin>>mat[i][j];
            a[i][j]=0;
        }
    }

    move(0,0,1,n,n,k);
    for(int i=0;i<n;i++){
        for(int j=0;j<n-1;j++){
            cout<<mat[i][j]<<" ";
        }
        cout<<mat[i][n-1];
        cout<<endl;
    }
    cout<<endl;
}
return 0;
}
一个数组记录是否访问过,一个数组记录走法,同类型的题目不管出成什么样都一样

发表于 2018-04-11 16:47:06 回复(0)
//每一行的最后一个数后不能有空格!
//2017腾讯校招模拟题 and 算法竞赛入门经典第二版
#include <stdio.h>
#include <string.h>
int main(void)
{
    int n=0;
    while(scanf("%d", &n)!=EOF){
        int x=0,y=0,j=1;
        int array[1024][1024];
        memset(array,0,sizeof(array));
        array[x][y]=j;
        j++;
        while(j<=n*n)
        {
            while(y<n-1 && array[x][y+1]==0){y++;array[x][y]=j;j++;}//y=4
            while(x<n-1 && array[x+1][y]==0){x++;array[x][y]=j;j++;}
            while(y>0 && array[x][y-1]==0){y--;array[x][y]=j;j++;}
            while(x>0 && array[x-1][y]==0){x--;array[x][y]=j;j++;}
        }
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n-1; ++j)
            {
                printf("%d ", array[i][j]);
            }
            printf("%d\n", array[i][n-1]);
        }
        printf("\n");
    }
    return 0;
}

发表于 2017-11-26 20:59:31 回复(0)

python solution

import sys


def generateMatrix(n):
    res = [[0 for i in range(n)] for j in range(n)]
    count = 1
    rowIndex1 = 0
    rowIndex2 = n - 1
    colIndex1 = n - 1
    colIndex2 = 0
    rowNum = n
    while rowNum >= 1:
        for i in range(colIndex2, colIndex1 + 1):
            res[rowIndex1][i] = count
            count += 1
        rowIndex1 += 1

        for i in range(rowIndex1, rowIndex2 + 1):
            res[i][colIndex1] = count
            count += 1
        colIndex1 -= 1

        for i in range(colIndex1, colIndex2 - 1, -1):
            res[rowIndex2][i] = count
            count += 1
        rowIndex2 -= 1

        for i in range(rowIndex2, rowIndex1 - 1, -1):
            res[i][colIndex2] = count
            count += 1
        colIndex2 += 1
        rowNum -= 2
    return res


for i in sys.stdin.readlines():
    matrix = generateMatrix(int(i))
    for line in matrix:
        print(" ".join(map(str, line)))
    print()
发表于 2017-11-17 11:05:20 回复(0)
#include <iostream>
#include <vector>
using namespace std;
int main()
{
	int length;
	while (cin >> length)
	{
		vector<vector<int> > data(length, vector<int>(length, 0));
		vector<int> number(length * 2 - 1, length);
		int cnt = 1;
		for (int i = 1; i < 2 * length - 1; i = i + 2)
		{
			number[i] = length - cnt;
			number[i + 1] = length - cnt;
			cnt++;
		}		
		if (length == 1)
		{
			cout << 1 << endl << endl;
			continue;
		}
		else
		{
			cnt = 1;
			int i = 0, j = -1;
			for (int k = 0; k < 2 * length - 1; k++)
			{
				if (k % 4 == 0)//向右
				{
					for (int x = 0; x < number[k]; x++)
					{
						j++;
						data[i][j] = cnt;
						cnt++;
					}
				}
				else if (k % 4 == 1)//向下
				{
					for (int x = 0; x < number[k]; x++)
					{
						i++;
						data[i][j] = cnt;
						cnt++;
					}
				}
				else if (k % 4 == 2)//向左
				{
					for (int x = 0; x < number[k]; x++)
					{
						j--;
						data[i][j] = cnt;
						cnt++;
					}
				}
				else  //向上
				{
					for (int x = 0; x < number[k]; x++)
					{
						i--;
						data[i][j] = cnt;
						cnt++;
					}
				}
			}
		}
		for (vector<vector<int> >::iterator it = data.begin(); it != data.end(); it++)
		{
			vector<int> res = *it;
			for (vector<int>::iterator k = res.begin(); k != res.end(); k++)
			{
				cout << *k;
				if (k != res.end() - 1)
					cout << " ";
				else
					cout << endl;
			}
		}
		cout << endl;
	}
	return 0;
}

发表于 2017-04-26 12:04:04 回复(0)
import java.util.*;
 
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            int n = sc.nextInt();
            int[][] arr = new int[n][n];
            int value = 1;
            //round为需要转的圈数.n为奇数时n/2+1圈,n为偶数时为n/2圈
            for (int round = 0; round < n / 2 + n % 2; round ++ ) {
                for (int i = round; i < n - round; i ++ ) { // 左→右
                    arr[round][i] = value ++ ;
                }
                for (int i = round + 1; i < n - round; i ++ ) { // 上→下
                    arr[i][n - round - 1] = value ++ ;
                }
                for (int i = n - round - 2; i >= round; i -- ) { // 右→左
                    arr[n - round - 1][i] = value ++ ;
                }
                for (int i = n - round - 2; i >= round + 1; i -- ) { // 下→上
                    arr[i][round] = value ++ ;
                }
            }
            for (int i = 0; i < n; i ++ ) {
                for (int j = 0; j < n; j ++ ) {
                    if(j == n - 1) System.out.println(arr[i][j]);
                    else System.out.print(arr[i][j] + " ");
                }
            }
            System.out.println();
        }
    }
}

发表于 2016-10-11 04:00:31 回复(0)
import java.util.Scanner;

public class Main {
public static void main(String agr[]){
int N,num=1,k,i0,j0;
Scanner input = new Scanner(System.in);
N=input.nextInt();
j0=N-1;
int a[][] = new int[N][N];
        for(k=0;k<=N/2;k++)
{
        i0=k;
for(int j=i0;j<=j0;j++)
a[i0][j]=num++;
for(int i=i0+1;i<=j0;i++)
a[i][j0]=num++;
for(int j=j0-1;j>=i0;j--)
a[j0][j]=num++;
for(int i=j0-1;i>i0;i--)
a[i][i0]=num++;
j0=j0-1;
}
for(int i=0;i<N;i++){
for(int j=0;j<N;j++)
System.out.print(a[i][j]+ " ");
System.out.println();
}
}

}

发表于 2016-05-27 17:05:29 回复(0)
按圈模拟到数组即可
#include <iostream>
#include <vector>
using namespace std;

int main()
{
	int n;
	while (cin >> n && n)
	{
		vector<vector<int> > m(n, vector<int>(n));
		int dir[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };

		int num = 1, sum = n - 1;
		for (int rou = 0; rou < (n + 1) / 2; ++rou)	// 循环第几圈
		{
			int x = rou, y = rou;
			for (int i = 0; i < 4; ++i)				// →↓←↑四个方向循环
			{
				for (int cou = 0; cou < sum; ++cou)	// 每圈有几个数字(减1防止重复打印)
				{
					m[x][y] = num;					// 打印
					++num;
					x += dir[i][0];					// 计算下一个位置
					y += dir[i][1];
				}
			}
			sum -= 2;								// 经过一圈,个数减2
		}
		if (n % 2) m[n / 2][n / 2] = n*n;			// 奇数情况,打印中心位置

		for (int i = 0; i < n; ++i)					// 输出
		{
			for (int j = 0; j < n; ++j)
				cout << (j ? " " : "") << m[i][j];
			cout << endl;
		}
		cout << endl;								// 每组打印一行空行
	}
	return 0;
}

编辑于 2015-12-20 18:54:39 回复(0)
#include "iostream"
using namespace std; 
int main(void){
	int E,S,W,N;//东南西北四个边界	
	int i,j,x,n;
	while(cin>>n){
        N = W = 0;
	E = S = n-1;
	int a[n][n];
	x = 1;
    while(N!=S && W!=E){
 	 for(i=N,j=W;j<=E;) a[i][j++] = x++;
         N++;
         if(N==S && W==E) break;
         for(i=N,j=E;i<=S;) a[i++][j] = x++;
         E--;
         if(N==S && W==E) break;
         for(i=S,j=E;j>=W;) a[i][j--] = x++;
         S--;
         if(N==S && W==E) break;
         for(i=S,j=W;i>=N;) a[i--][j] = x++;
         W++;
         if(N==S && W==E) break;
    }
    a[N][W] = x;
for(i=0;i<=n-1;i++){
	for(j=0;j<=n-2;j++){
	cout<<a[i][j]<<" ";	//千万不要用ends,搞了半天通不过是因为这个。。。
	}
	cout<<a[i][n-1]<<endl;//最后一个直接换行
}
    cout<<endl;
}
    return 0;
}

发表于 2015-09-24 00:26:46 回复(0)