面试题-螺旋矩阵(模拟)

         最近无聊的很,看了看一些基础的面试题,虽说简单点,但还是能学到一点东西的。
就比方main函数结束之后还能执行函数吗?答案是可以,使用atexit注册一个函数就可以了。
下面重点谈谈这个螺旋矩阵!
关于螺旋矩阵的说法不一,这里指的是形如
           21  22................
           20  7  8  9  10
           19  6  1  2  11
           18  5  4  3  12
           17  16 15 14 13
的矩阵。

问题有两个:
1. 编程实现输出这个矩阵
2. 设1点的坐标是(0,0),x方向向右为正,y方向向下为正.例如:7的坐标为(-1,-1) ,2的坐标为(0,1),3的坐标为(1,1).编程实现输入任意一点坐标(x,y),输出所对应的数字。

1. 第一个问题我是采用模拟进行构造的,可以看到从1开始的方向变化始终是 right->down->left->up,
所持续走的长度为1->1->2->2->3->3->...,发现了这个规律不难写出代码了!注意下面我把1的位置设置
在((n-1)/2, (n-1)/2)的位置。

None.gif void  Simulate( int  n)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int x, y;
InBlock.gif    x 
= y = (n - 1/ 2//1的位置
InBlock.gif
    data[x][y] = 1;
InBlock.gif    
int len = 1;
InBlock.gif    
int count = 0;
InBlock.gif    
int num = 2;
InBlock.gif    DIRECTION dir 
= RIGHT;
InBlock.gif    
while(num  <= n * n)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
for(int i = 0; i < len; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
switch(dir)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif            
case LEFT:
InBlock.gif                
--y;    break;
InBlock.gif            
case RIGHT:
InBlock.gif                
++y;     break;
InBlock.gif            
case UP:
InBlock.gif                
--x;    break;
InBlock.gif            
case DOWN:
InBlock.gif                
++x;    break;
InBlock.gif            
default:    break;
ExpandedSubBlockEnd.gif            }

InBlock.gif            data[x][y] 
= num++;
ExpandedSubBlockEnd.gif        }

InBlock.gif        count
++;
InBlock.gif        
if(count == 2)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            count 
= 0;
InBlock.gif            len
++;    
ExpandedSubBlockEnd.gif        }

InBlock.gif        dir 
= (DIRECTION)((dir + 1% 4);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}


2. 第二个问题我也是先找出规律,然后进行模拟。
首先,不难看出n*n的螺旋矩阵的右下角的坐标一定是(m, m),这里m=n-1
通过观察,可以看出 n=1的时候,右下角(0,0)的值为1,当n=2的时候,右下角(1,1)的坐标值为(3,3),当n=3的时候,右下角(2,2)的坐标值为13.直觉告诉我,这个值是关于n的二次函数,设f(n) = a*n^2 + b*n + c
联立方程组,可以求得a,b,c。 最终算出来的f(n) = 4*n^2 - 2*n + 1
下面再根据(x,y)和右下角(n-1,n-1)之间的关系,计算出值即可。这里要注意当x的值与n-1相同时,应优先考虑y与-m是否有联系。这就要求在函数中要注意x,y的判断先后顺序了。
代码如下:

None.gif // 以(1,1)所在位置作为原点,向右作为x正半轴,向下作为y正半轴
None.gif
int  GetValue( int  x,  int  y)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
int m = max(abs(x), abs(y));
InBlock.gif    
int rightBottom = m * m * 4 - 2 * m + 1;
InBlock.gif    
int value = 0;
InBlock.gif    
if(x == -m)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        value 
= rightBottom + 2 * m + m - y;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else if( y == m)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        value 
= rightBottom + m - x;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else if(y == -m)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        value 
= rightBottom + 4 * m + x + m;
ExpandedSubBlockEnd.gif    }

InBlock.gif    
else if( x == m )
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        value 
= rightBottom - (m - y);
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif
InBlock.gif    
return value;
ExpandedBlockEnd.gif}

None.gif


完整代码如下:
ContractedBlock.gif ExpandedBlockStart.gif
#include <iostream>
#include 
<cstdlib>
#include 
<algorithm>

using namespace std;

const int N = 100;

int data[N + 1][N + 1];

enum DIRECTION
{
    RIGHT, DOWN , LEFT, UP
};

//模拟整个过程
void Simulate(int n)
{
    
int x, y;
    x 
= y = (n - 1/ 2//1的位置
    data[x][y] = 1;
    
int len = 1;
    
int count = 0;
    
int num = 2;
    DIRECTION dir 
= RIGHT;
    
while(num  <= n * n)
    {
        
for(int i = 0; i < len; i++)
        {
            
switch(dir)
            {
            
case LEFT:
                
--y;    break;
            
case RIGHT:
                
++y;     break;
            
case UP:
                
--x;    break;
            
case DOWN:
                
++x;    break;
            
default:    break;
            }
            data[x][y] 
= num++;
        }
        count
++;
        
if(count == 2)
        {
            count 
= 0;
            len
++;    
        }
        dir 
= (DIRECTION)((dir + 1% 4);
    }
}

//打印螺旋矩阵
void Output(int n)
{
    
int i, j;
    
for(i = 0; i < n; i++)
    {
        cout 
<< data[i][0];
        
for(j = 1; j < n; j++)
            cout 
<< "\t" << data[i][j];
        cout 
<< endl;
    }
}

//以(1,1)所在位置作为原点,向右作为x正半轴,向下作为y正半轴
int GetValue(int x, int y)
{
    
int m = max(abs(x), abs(y));
    
int rightBottom = m * m * 4 - 2 * m + 1;
    
int value = 0;
    
if(x == -m)
    {
        value 
= rightBottom + 2 * m + m - y;
    }
    
else if( y == m)
    {
        value 
= rightBottom + m - x;
    }
    
else if(y == -m)
    {
        value 
= rightBottom + 4 * m + x + m;
    }
    
else if( x == m )
    {
        value 
= rightBottom - (m - y);
    }
    

    
return value;
}

void TestPos(int n)
{
    
int i, j;
    
for(i = 0; i < n; i++)
    {
        cout 
<< GetValue(0 - (n - 1/ 2, i - (n - 1/ 2);
        
for(j = 1; j < n; j++)
            cout 
<< "\t" << GetValue(j - (n - 1/ 2, i - (n - 1/ 2);
        cout 
<< endl;
    }
}

int main()
{
    
int n;
    
while(cin >> n)
    {
        
if(n <= 0 || n > 100)
        {
            cerr 
<< "Size error!" << endl;
            
break;
        }
        
else
        {
            Simulate(n);
            Output(n);
            cout 
<< "*******************" << endl;
            TestPos(n);
        }
    }

    
return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值