蛇形填数的代码及分析

在大佬的指引下在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));
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lxiaowangtongxue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值