在大佬的指引下在CSDN刷了一下算法,现在还在基础部分,然后碰到了蛇形填数,比较感兴趣,于是自己写了一遍,也加入了自己遇到的一些问题
蛇形填数
从1开始安放数字,根据对角线来依次填充数字,具体如图所示:
思考过程
其实我们可以分为两个部分来看,一个是往坐下走,一个是往右上走,明显这两部分的代码是有差别的。我们现在要思考的关键就是什么时候往左下,什么时候往右上。其实我们可以发现有两个转折点,分别是到了最顶部和最左边的时候,所以我们以这两个为两部分的分割点。我们设置一个row来代表行,一个col来代表列,右上就是col++,row--的循环过程,左下就是col--,row++的循环过程,当col或者row等于0时说明达到了一个边界,如果是row=0,说明达到了顶部,col++来完成右移,如果col=0,说明到达了左边界,row++来完成下移。
代码展示
public class NumberOfSnake {
private int[][] num = new int[15][15];//随便定义一个二维数组,空间可以稍微给大些
private int col = 0;//表示列
private int row = 0;//表示行
public NumberOfSnake(){
num[0][0] = 1;//完成第一个格子的装填
int i = 2;//开始装数
while (i <= 100){//这里是一个结束范围,但并不是在100处就结束了,如果要在100处结束,后面的判断均要加i<=100
while (col >-1 && row > -1){//左下移动,判断为-1是因为0的时候也要进入来装数字
if (row == 0) col++;//如果此时为顶部,向右平移一格
num[row][col] = i;
col--;//向左移动一格
row++;//向下移动一格
i++;
}
col++;//多移动了一个左下,把列还原
row--;//把行还原
while (col >-1 && row >-1){//右上移动
if(col == 0) row++;//此时为左边界,向下平移一格
num[row][col] = i;
row--;
col++;
i++;
}
row++;//多移动了一个右上,把行还原
col--;//把列还原
}
}
public int getNum(int r, int l) throws Exception {
if (r > 9 || l > 9 || r < 0 || l < 0) throw new Exception("输入范围错误");
int a = num[r][l];
return a;
}
public static void main(String[] args) throws Exception {
NumberOfSnake nos =new NumberOfSnake();
System.out.println(nos.getNum(3,3));
}
}
过程中的问题
1.
为什么会多移动:因为在左下移动的时候,col=0也能进入循环,完成左边界元素的安放,但此时col--使得col变为了-1,row++使得row往下移动了一行,已经超出了边界,如果此时不还原,首先col=-1无法进入后面的循环,但是仅有col++,row不还原,那么在右上移动第一个判断col=0时会再往下移动一行,此时就跳了一个对称轴
row不还原:
row还原(代码思路):
2.为什么不是只装100
因为100是最外层的判断,而100在15*15的格子中并不处于边界,此时还在内部循环,如果想要只装入100可以在内部循环中也设置i<=100
蛇形填数的升级
在编辑文章的过程中突然想到,100不是恰好能装入一个10*10的放格里面吗,那我们把代码升级一下,我们现在依旧是蛇形填数,输入一个数字,如8,那么就用8*8的格子装入64个数字
如图所示:
思考过程:
在之前的代码上我们要做出相应的调整,首先就有一个问题:按照之前的代码在填到36以后,37会填到下一排,但实际应该往右填数,这种情况的出现是我们没有设置右边界和下边界的判断,当到了右边界时,不应该往右再移动,而是往下移动,当到了下边界时,也不能往下再移动,而是往右移动,这样才能填满一个8*8的格子。
根据填入数字的不同,在第一次抵达右边界时会出现两种情况:
第一种:向右上填充时先达到顶部,往右移动一格后恰好到达右顶角,此时代码不需要改变,与之前一样。第二种:如果是向右上时达到了右顶角,此时不需要再往右移动一格而是向下移动一格,后续达到右边界应与第二种情况一致。达到底部的情况与之相似,不再赘述。
代码展示:
package CSDN;
import java.util.Scanner;
public class NumberOfSnake {
private int[][] num;
private int col = 0;//表示列
private int row = 0;//表示行
int n;
public NumberOfSnake(int m) {
num = new int[m][m];
n = m - 1;
num[0][0] = 1;//完成第一个格子的装填
int i = 2;//开始装数
while (i <= m*m) {
{
while (col > -1 && row > -1 && col <= n && row <= n) {//左下移动
if (row == 0 && col != n) {//未到达右边界之前的过程
col++;//如果此时为顶部,向右平移一格
}
else if (col == n){//这里一定是eles if否则会出现,进入第一个if右移动了以后满足col=n导致多移动一格横排
row++;//如果是达到了右边界,不再右移动而是向下移动
}
num[row][col] = i;
col--;//向左移动一格
row++;//向下移动一格
i++;
}
col++;//多移动了一个左下,把列还原
row--;//把行还原
}
while (col > -1 && row > -1 && col <= n && row <= n) {//右上移动
if (col == 0 && row != n) row++;//未达到下边界之前的过程
else if (row == n){
col++;
}
num[row][col] = i;
row--;
col++;
i++;
}
row++;//多移动了一个右上,把行还原
col--;//把列还原
}
}
public int getNum(int r, int l) throws Exception {
if (r > n || l > n || r < 0 || l < 0) throw new Exception("输入范围错误");
int a = num[r][l];
return a;
}
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入数字:");
int m = scanner.nextInt();
NumberOfSnake nos = new NumberOfSnake(m);
System.out.println(nos.getNum(3, 3));
}
}