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

来源:互联网 发布:java string 添加元素 编辑:程序博客网 时间:2024/05/21 12:46
/*
顺时针打印矩阵:
输入一个矩阵,按照从外向里顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵:
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;
}
0 0