美文网首页System.keepCoding();
【算法题解】回溯算法--顺时针填充矩阵

【算法题解】回溯算法--顺时针填充矩阵

作者: 陳年风楼 | 来源:发表于2017-07-16 22:24 被阅读0次

简书是一个不错的平台,可是种类繁杂,毕竟不是一个专属于程序员的博客平台,一直很犹豫是否要把博客从CSDN转移到这里来。最终还是抵挡不了平台的诱惑啊。不过说到底,写在哪里都一样,写下来能够加深自己的印象,同时能够给一些要学的人一些干货,何乐而不为。那么,就从一道算法题目开始吧。


顺时针填充矩阵

题目:
给出一个二维数组,要求按照顺时针将二维数组从1~n填充。
例如:4*4的二维数组,填充之后为:

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

题解:
这道题的解题思路有很多,我只在这里说明一种解法:使用回溯算法求解。所谓回溯算法,实际上是一种向前探索的思路。它会在求解的时候向前探索,把可能出现的情况作为路径,当这条路无法得到结果时,它会回过头,探索下一条可能出现的情况。
那么思路如下:首先,矩阵要实现顺时针填充,必须要有一个控制方向的“方向盘”。如例子中的矩阵,当一开始向前填充数字的时候,没有方向的控制,结果只能是下标越界。当有了“方向盘”之后,数字的填充还需要第二个东西,就是“转弯指示器”。当数字填充到数组边界时,“转弯指示器”会提醒“方向盘”转弯。第三,也就是在数组填充完成后,停止的判断了。

我们可以把以上思路先用伪代码表示如下

//0、初始的方向为向右,开始坐标为(1,1)
//1、当前坐标为(x,y),方向为:dir。“填充者”开始工作,填充数字。
     向坐标(x,y)填入当前数字。
//2、转弯指示器和停止判断器开始工作,判断是否到达边界需要转弯,
     以及是否填充完成需要停止。转弯,执行第5步;停止,执行return。
     否则坐标沿着方向指向向接下来的位置移动,
     即改变(x,y),然后执行第1步。
//4、转弯:方向顺时针改变一步,然后然后坐标按照当前更改过的方向移动,执行步骤1。

那么,“转弯指示器”如何设置呢?
我们可以设置这样一个数组:
int move[][] = {{0,1},{1,0},{0,-1},{-1,0}};
以及这样一个指针下标:
int direction = 0;
当direction的值为0,1,2,3时,分别对应move数组的4个一维数组,用以表示右、下、左、上四个方向。那么如何在程序中使用这个方向指示器呢?完整代码如下:

import java.util.Scanner;
public class Main {
    public static void main(String []args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        //输入数字n,设置n*n的数组
        CreateA(n);
      } 
      public static void CreateA(int n){
      //初始化矩阵为长宽n+2的二维数组,最外层一圈填值为0,其余为-1
        int[][] a = new int[n+2][n+2];
        for (int i = 1; i < a.length-1; i++) {
            for (int j = 1; j < a[i].length-1; j++) {
                a[i][j] = -1;
            }
        }
        //方向数组 该数组为本算法的关键
        int move[][] = {{0,1},{1,0},{0,-1},{-1,0}};
        int direction = 0;
        int k= 1;
        Go(k, 1, 1, n, a, move, direction);
        //输出填好的蛇形矩阵
        for (int i = 1; i < a.length-1; i++) {
            for (int j = 1; j < a[i].length-1; j++) {
                System.out.print("\t"+a[i][j]);
            }
            System.out.println();
        }
      }
//  填写矩阵,矩阵最外层的一圈为0,其他值为-1,当遇到-1的时候才给矩阵里填值
      public static void Go(int k,int x,int y,int n,int a[][],int move[][],int direction){
          a[x][y]  = k++;
          if(k> n*n)
              return;
          while(a[x+move[direction][0]][y+move[direction][1]]!= -1){
          //方向由 右、下、左、上循环
              direction = (direction+1)%4;
          }
          //x,y为即将走上的下一个格子
          x = x+move[direction][0];
          y = y+move[direction][1];
          Go(k, x, y, n, a, move, direction);
      }
}

相关文章

  • 【算法题解】回溯算法--顺时针填充矩阵

    简书是一个不错的平台,可是种类繁杂,毕竟不是一个专属于程序员的博客平台,一直很犹豫是否要把博客从CSDN转移到这里...

  • 顺时针打印矩阵

    题目:顺时针打印矩阵(算法课第四课) 对于一个矩阵,请设计一个算法从左上角(mat[0][0])开始,顺时针打印矩...

  • 分支限界

    类似【回溯算法】,也是一种在问题的解空间树上搜索问题解的算法。但一般情况下,【分支限界】与【回溯算法】的求解目标不...

  • 回溯算法

    回溯算法 回溯算法介绍   回溯算法并不是非常复杂的算法, 很多人接触过但是未必知道这是回溯算法; 典型的回溯算法...

  • 回溯算法:八皇后问题和0-1背包问题

    文章结构 如何理解回溯算法 回溯算法的经典应用 完整源码 图片来源 1. 如何理解回溯算法 1.1 什么是回溯算法...

  • Algorithm进阶计划 -- 回溯算法

    滑动窗口算法回溯算法框架回溯算法运用 1. 回溯算法框架 回溯算法,是类似枚举的搜索尝试过程,主要是在搜索尝试过程...

  • 46. Permutations.go

    回溯算法需要注意的是,填充结果的时候,需要copy一个slice

  • 回溯算法总结

    回溯法学习总结 回溯算法也是算法导论中常用的算法,回溯算法类似于暴力求解算法,经常用在求可能解的问题。下面我将从三...

  • 77. Combinations.go

    回溯算法

  • 顺时针输出数字矩阵

    Q: 之前朋友跟我聊了道算法题,是顺时针输出数组矩阵,如图1所示: 简单写了下算法,语言无所谓,思路都差不多,我用...

网友评论

    本文标题:【算法题解】回溯算法--顺时针填充矩阵

    本文链接:https://www.haomeiwen.com/subject/zbsxkxtx.html