这是对蓝桥杯上例题代码的学习理解和注解
例题代码给了3个语言的代码
C++ Java Python
我学习了前两个语言的代码并全部用Java重写并注解了一遍
C++的代码要比Java的更加清晰,但是行数要比Java更多
先上用Java重写后的C++版本
public static void function1()
{
Scanner in=new Scanner(System.in);
int m,n;
m=in.nextInt();//行
n=in.nextInt();//列
int[][] a=new int[m+1][n+1];
int[][] vis=new int[m+1][n+1];
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
a[i][j]=in.nextInt();
}
}
int x=1;
int y=1;
System.out.print(a[x][y]);//先把输出起点的位置 后面的操作都是先走路再输出 所以必须先把起点输出
vis[1][1]=1;//标记起点
int sum=1;//可走总步数=总数字个数-1(起点)
while(sum<n*m)//一次循环走完一个圈子 越走越小
{
//先往下
while(x+1<=m && vis[x+1][y]==0)//若下一个没越界且没有走过
{
x++;//往下走
System.out.print(" "+a[x][y]);//输出该点的数字f
vis[x][y]=1;//标记为已走过
sum++;//可走的步数-1
}
//再往右
while(y+1<=n && vis[x][y+1]==0)
{
y++;
System.out.print(" "+a[x][y]);
vis[x][y]=1;
sum++;
}
//再往上
while(x-1>=1 && vis[x-1][y]==0)
{
x--;
System.out.print(" "+a[x][y]);
vis[x][y]=1;
sum++;
}
//再往左
while(y-1>=1 && vis[x][y-1]==0)
{
y--;
System.out.print(" "+a[x][y]);
vis[x][y]=1;
sum++;
}
}
}
大致思路就是:
以(1,1)为起点作为整个数表的起点
因此数组列和行要比输入的多1
核心思路:0.计算好要移动的总步数->1.获取下一个格子->2.判断是否符合满足条件->3.移动到4.这个格子并输出内容->5.将此格子标记为已走过->6.步数-1->重复1
从起点开始走
我们就可以先把起点格子中的数输出
然后在进行上述核心思路的方法
这里注意是先判断再移动再输出,顺序不能搞乱了
即可得到答案
Java的例题代码与C++的代码核心思路大体一致 唯一的区别就是对起点的处理
以及在处理移动时的手段不同
Java版本
public static void function2()
{
Scanner in=new Scanner(System.in);
int m,n;
m=in.nextInt();//行
n=in.nextInt();//列
int[][] a=new int[m][n];
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
a[i][j]=in.nextInt();
}
}
int[][] dir=new int[][]{{1,0},//往下 d=0
{0,1},//往右 d=1
{-1,0},//往上 d=2
{0,-1}};//往上 d=3
//初始坐标 起点上方
int x=-1;
int y=0;
int sum=0;//总步数
int d=0;//控股之方向 d=
while(sum<n*m)
{
sum++;//步数-1
//获取下一个格子的坐标
int nx=x+dir[d][0];
int ny=y+dir[d][1];
if(nx<0 || ny <0 || nx>=m || ny>=n || a[nx][ny]==-1)//判断 下一个格子 是否超过上界 下界 左界 右界 是否重复
{
//如果越界或重复走过
/*0->1 d=d+1=0+1=1%4=1;
1->2 d=d+1=1+1=2%4=2;
2->3 d=d+1=2+1=3%4=3;
3->0 d=d+1=3+1=4%4=0
* */
d=(d+1)%4;//转向
//获取下个格子的坐标
nx=x+dir[d][0];
ny=y+dir[d][1];
//下一个格子可以走 移动到下一个格子
x=nx;
y=ny;
}else{
//下一个格子可以走 移动到下一个格子
x=nx;
y=ny;
}
System.out.print(a[x][y]+" ");//将格子输出
a[x][y]=-1;//标记已走过
}
}
核心思路仍和C++的一样:
0.计算好要移动的总步数->1.获取下一个格子->2.判断是否符合满足条件->3.移动到4.这个格子并输出内容->5.将此格子标记为已走过->6.步数-1->重复1
步数的减少我认为先进行和后进行应该是没有区别的
与C++版本不同的是
Java版本的例题代码使用了一个二维数组dir[][]来控制移动
首先他仍旧是先获取下一个格子的坐标
这里获取格子坐标的时候用的是当前坐标+dir的偏移来得到的
dir则是通过变量d来控制方向->dir[d][0]或者dir[d][1]
回形取数的每一圈是下(x++)->左(y++)->上(x--)->右(y--)
因此dir({1,0},{0,1},{-1,0},{0,-1}}分别代表了
(x++,y不变)
(x不变,y++)
(x--,y不变)
(x不变,y--)
如果判断发现越界或者已走过
通过改变d的值来转换方向
这里d的值变化是1->2->3->0
因此用了(d+1)%4
之后便是获取下个格子-输出-标记-重复
如果判断没有越界和未走过
则就执行else的正常流程
下个格子-输出-标记-重复
这里标记是对原数表中的值直接修改为-1
与C++版本的单独列一个数组并不同