您的位置:首页 > 职场人生

剑指Offer:面试题20 顺时针打印矩阵

2014-09-08 19:46 561 查看
/*

顺时针打印矩阵:

输入一个矩阵,按照从外向里顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

则依次打印出数字:

1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入的第一行包括两个整数m和n(1<=m,n<=1000):表示矩阵的维数为m行n列。

接下来的m行,每行包括n个整数,表示矩阵的元素,其中每个元素a的取值范围为(1<=a<=10000)。

输出:

对应每个测试案例,输出一行,

按照从外向里以顺时针的顺序依次打印出每一个数字,每个数字后面都有一个空格。

样例输入:

4 4

1 2 3 4

5 6 7 8

9 10 11 12

13 14 15 16

样例输出:

1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10

分析这是一个蛇形矩阵问题:

类似于迷宫,最关键的是解决到达何处时,应该走令一个方向。

通过行号和列号,以及剪枝数组来进行确认

*/

/*

关键:

采用试探法

1 从左向右,纵坐标不能超过n,为了对下一个元素采用试探法:

if(y + 1 < n && !bMark[x][y+1])

{

printf("%d ",iMatrix[x][y+1]);

}

*/

/*

关键:

1 int iCnt = 1;//这边计数器必须从1开始,否则陷入无限循环。到m*n跳出,共有m*n-1+1=m*n个元素

2 //采用试探法从左向右,防止y越界。这里最牛逼的方法就是:通过对横纵坐标的累加或累减以剪枝判定下一次蛇形的上下界

while(iy + 1 < n && !bMark[ix][iy+1])

{

printf("%d ",iMatrix[ix][++iy]);

bMark[ix][iy] = true;

++iCnt;

}

//从上向下,防止x越界

while(ix + 1 < m && !bMark[ix+1][iy])

3注意,这里采用了对4个方向的模拟操作

*/

#include <stdio.h>

#include <string.h>

const int MAXSIZE = 1001;

int iMatrix[MAXSIZE][MAXSIZE];

bool bMark[MAXSIZE][MAXSIZE];

int go[][2] =

{

{0,1},

{1,0},

{0,-1},

{-1,0}

};

void snakeNum(int m,int n)

{

int ix = 0,iy = 0;

int iCnt = 1;//这边计数器必须从1开始,否则陷入无限循环。到m*n跳出,共有m*n-1+1=m*n个元素

printf("%d ",iMatrix[ix][iy]);

bMark[ix][iy] = true;

while(iCnt < m*n)

{

//采用试探法从左向右,防止y越界。这里最牛逼的方法就是:通过对横纵坐标的累加或累减以剪枝判定下一次蛇形的上下界

while(iy + 1 < n && !bMark[ix][iy+1])

{

printf("%d ",iMatrix[ix][++iy]);

bMark[ix][iy] = true;

++iCnt;

}

//从上向下,防止x越界

while(ix + 1 < m && !bMark[ix+1][iy])

{

printf("%d ",iMatrix[++ix][iy]);

bMark[ix][iy] = true;

++iCnt;

}

//从右向左,防止y越界

while(iy - 1 >= 0 && !bMark[ix][iy-1])

{

printf("%d ",iMatrix[ix][--iy]);

bMark[ix][iy] = true;

++iCnt;

}

//从下向上,防止x越界,

while(ix - 1 >= 0 && !bMark[ix-1][iy])

{

printf("%d ",iMatrix[--ix][iy]);

bMark[ix][iy] = true;

++iCnt;

}

}

printf("\n");

}

void snakeMatrix(int m,int n)//蛇形矩阵

{

int ix = 0,iy = 0;//设置起始节点,ix表示的是行号,然后从左向右行号不变,所以

int iCnt = 0,i = 0;

while(iCnt < m*n)

{

//先遍历,后面再更新位置

while(ix >= 0 && ix < m && iy >= 0 && iy < n)//如果没有访问过,且行号和列号均在正常范围内

{

if(bMark[ix][iy])//如果已经访问过,直接跳过

{

ix += go[i][0];

iy += go[i][1];

continue;

}

iCnt++;

printf("%d ",iMatrix[ix][iy]);

bMark[ix][iy] = true;

ix += go[i][0];

iy += go[i][1];

}

i++;

if(ix >= m)

{

ix--;

}

if(iy >= n)

{

iy--;

}

if(ix < 0)

{

ix++;

}

if(iy < 0)

{

iy++;

}

if(i == 4)//如果一遭都走过了,那么令i重新为0

{

i = 0;

}

}

}

void process()

{

int m,n;

while(EOF != scanf("%d %d",&m,&n))

{

if(n < 1 || n > 1000 || m < 1 || m > 1000)

{

continue;

}

memset(iMatrix,0,sizeof(iMatrix));

memset(bMark,0,sizeof(bMark));

for(int i = 0 ; i < m ; i++)

{

for(int j = 0; j < n; j++)

{

scanf("%d",&iMatrix[i][j]);

}

}

snakeNum(m,n);

}

}

int main(int argc,char* argv[])

{

process();

getchar();

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: