螺旋队列(螺旋矩阵)——创新工场面试总结2

创新工场会有一个统一的笔试,笔试过了之后会有面试,这个面试过了之后,可以参加后面的双选会,双选会的单位一般是从创新工场孵化成功的企业。

今天参的是第一场面试。开始聊项目,后面问了一个螺旋矩阵的问题,螺旋矩阵的问题见过,但是吃亏就吃在没有把自己的思路讲清除,这里再梳理一下。

有一个n*n的矩阵如下排列,将矩阵打印出来。

eg:


解法一:首先分配一个n*n的整型数组,根据螺旋的递增顺序,将对应的数组中元素赋值。时间复杂度O(n^2),空间复杂度O(n^2)。面试官可能希望我给出这个思路,但是由于已有知识,一开始就没考虑到这种做法。下面有一种时间复杂度相同,空间复杂度O(1)的方法。

解法二:先看一个“从中心开始递增的螺旋队列问题”,

有一个n*n的矩阵如下排列,将矩阵打印出来。

eg:


假如能打印已知矩阵的一个元素为x,那么只需要将该元素用n^2+1-x替换掉就可以得到从外层开始递增的螺旋队列。如何得到x?

分四种情况讨论:(i,j)表示相对于中心(0,0)的横坐标,纵坐标

	if(i==-layer)			//在上边,
		v=v-layer-j;		//随横坐标递减
	else if(i==layer)		//在下边
		v=v-5*layer+j;		//随横坐标递增
	else if(j==layer)		//在右边
		v=v-3*layer-i;	
	else 				//在左边
		v=v-3*layer+i;


显然这两个问题的差别不仅在此,原问题中n可以是奇偶数,而归约的问题中n只能是奇数。那么当n是偶数的时候如何处理呢。可以观察下面矩阵

将该矩阵分成三部分

1*4

3*3 3*1

左下角3*3的矩阵可以通过类似上面的分析得到,但由于上面1*n和左面(n-1)*1的元素数,因此需要在原来的基础上加上2*n-1。即(n-1)^2-x+2n。x的获取方法与上面类似,当还需要一个180的旋转。

至此问题分析结束,下面给出完整代码:

#include <stdio.h>
#define max(a,b) (a)>(b)?(a):(b)
#define abs(a) (a)>0?(a):(-(a))
int getX(int i,int j)
{
	int layer=max(abs(i),abs(j));//求出层数
	
	int v=layer*2 +1;
	v=v*v;
	if(i==-layer)
		v=v-layer-j;
	else if(i==layer)
		v=v-5*layer+j;
	else if(j==layer)
		v=v-3*layer-i;
	else 
		v=v-3*layer+i;
	return v;
}
void printEvenM(int n)
{
	int sum=(n-1)*(n-1)+2*n;
	int layerN=n/2-1;
	for(int i=0;i<n;i++)
		printf("%d ",i+1);
	printf("\n");
	for(int i=-layerN;i<=layerN;i++)
	{
		for(int j=-layerN;j<=layerN;j++)
		{
			printf("%d ",sum-getX(-i,-j));		//-i,-j表示旋转180度
		}
		printf("%d\n",n+i+layerN+1);
	}
}

void printOddM(int n)
{
	int sum=n*n+1;
	int layerN=n/2;
	for(int i=-layerN;i<=layerN;i++)
	{
		for(int j=-layerN;j<=layerN;j++)
		{
			printf("%d ",sum-getX(i,j));	
		}
		printf("\n");
	}
}
void printM(int n)
{
	if(n%2)
		printOddM(n);
	else
		printEvenM(n);
}


int main()
{
	printM(6);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值