数字螺旋输出,O(1)空间复杂度解法

问题定义:
输入n,将数字1...n螺旋输出。
举例:
n=2,输出结果为
1 2
4 3

n=3,输出结果为
1 2 3
8 9 4
7 6 5

解题:
此题解法很多,常见的多要借助二维数组来存储待输出的结果,空间复杂度为O(n*n)
这里介绍一个不借助二维数组的方法,将空间法复杂度降为O(1)。
引入层的概念,用 l 表示,如:
1 2 3
8 9 4
7 6 5 有2层,1、2、3、4、5、6、7、8是第0层(从0计数),9是第1层。

n*n矩阵所含层数 L = ceil(n/2), 取上限。如3*3矩阵有2层,4*4矩阵有2层, 5*5矩阵有3层。
每一层都是一个矩形,有4条边(只有一个数组成的层,看成矩形点),如:
1 2 3
8 4
7 6 5 
矩形大小 s 用边长度来定义,如上面矩形,其大小为3(边包含3个元素)。

算法关键处:找到二维矩阵下标值 i,j 与 l,n的关系,进而找到每一个ij位置所放的数与l,n的关系。
对于二维矩阵中任一位置A[i,j], A[i,j]所处的层 l = min(i, n-j-1) (i<=j) or l = min(j, n-i-1) (i>j)

第 l 层的矩形大小 s = n-2*l
第 l 层包含的元素个数为 (n-2*l-1)*4
第 l 层之外的所有层包含的元素个数为(0 至 l-1层):sw = 4*l*(n-l)

A[i,j]位置应放置的数为:
//A[i,j]位置出于矩形的上边
if(i=l && i<=j) A[i,j] = sw + j-l+1
//A[i,j]位置出于矩形的右边
if(j=n-1-l && i<=j) A[i,j] = sw + s + i-l
//A[i,j]位置出于矩形的下边
if(i=n-1-l && i>=j) A[i,j] = sw + 2*s -1 + n-1-l-j
//A[i,j]位置出于矩形的左边
if(j=l && i>=j) A[i,j] = sw + 3*s-2 + n-1-l-i

实现代码如下:

int main()
{
int n,l;
scanf("%d", &n);

int i,j,value;
for(i=0; i<n; i++)
{
for(j=0; j<n; j++)
{
if(i <= j) l = min(i, n-j-1);
else l = min(j, n-i-1);

int sw = 4*l*(n-l);

if(i==l && i<=j) { value = sw + j-l+1; }
else if(j==(n-1-l) && i<=j) { value = sw + (n-2*l) + i-l; }
else if(i==(n-1-l) && i>=j) { value = sw + 2*(n-2*l)-1 + n-1-l-j;}
else if(j==l && i>=j) { value = sw + 3*(n-2*l)-2 + n-1-l-i; }
else value = -1;

printf("%5d", value);
}
printf("\n");
}

system("pause");
return 0;
}


另一种解法: 空间复杂度为O(N*N) 时间复杂度O(n*n)

模拟行走过程(或迷宫走法),四个方向(→↓←↑)循环变换。

int main()
{
int a[N][N] = {0};

int n;
scanf("%d", &n);

int di=0, dj=1;
int i=0, j=-1;
int count = 1;
while(count<=n*n)
{
if(i+di >= 0 && i+di < n && j+dj >= 0 && j+dj < n && a[i+di][j+dj] == 0) a[i+=di][j+=dj] = count++;
else if(di==0 && dj==1) di=1, dj=0;
else if(di==1 && dj==0) di=0, dj=-1;
else if(di==0 && dj==-1) di=-1, dj=0;
else if(di==-1 && dj==0) di=0, dj=1;
}

for(i=0; i<n; i++)
{ 
for(j=0; j<n; j++)
printf("%5d", a[i][j]);
printf("\n");
}

system("pause");
return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值