Java 小例子:按照顺时针或逆时针方向输出一个数字矩阵

原创 2015年11月19日 11:00:40

题目:按照指定的长宽和输出方向,从外向内打印一个从 1 开始的数字矩阵,矩阵的开始位置在左上角。如下图
这里写图片描述

代码及注释如下:

public class NumberMatrix {

    public static void main(String[] args) {
        int width = 25;
        int height = 12;
        boolean clockwise = false;

        outputMatrix(width, height, clockwise);
    }

    /**
     * 按照指定的长宽和输出方向,从外向内打印一个从 1 开始的数字矩阵,矩阵的开始位置在左上角。
     *
     * @param width     矩阵宽度
     * @param height    矩阵高度
     * @param clockwise 是否是顺时针方向
     */
    private static void outputMatrix(int width, int height, boolean clockwise) {

        // 首先判断最大数字的位数,以决定输出如何对齐
        int numLength = (int) Math.log10(width * height) + 1;

        // 决定输出的格式(最大位数 + 1个空格)
        String format = "%" + (numLength + 1) + "d";

        // 定义要输出的二维数组,注意维度是从高到低的
        // 此时 matrix 中所有元素的值都是 0
        int[][] matrix = new int[height][width];

        // 定义一个位置指针和一个计数器,位置指针进行移动,而计数器负责递增,递增后的数字
        // 被填充进矩阵,当 width * height 个数字填充完毕,这个矩阵就完成了。
        // 注意这里位置指针的第一个元素对应 matrix 的第一个维度 y,第二个元素对应第二个维度 x。
        int[] pointer = {0, 0};
        int counter = 1;

        // 定义当前移动的方向:1、2、3、4 分别表示上、右、下、左。
        // 顺时针的起始方向为右,逆时针的起始方向为下。
        int direction = clockwise ? 2 : 3;

        // 开始循环填充,每个填充分为三步
        for (int i = 1, max = width * height; i <= max; i++) {

            // 1. 填充内容
            int y = pointer[0];
            int x = pointer[1];
            matrix[y][x] = counter;

            // 2. 计数器自增
            counter += 1;

            // 3. 移动到下一个位置,因为这地方比较复杂,所以开个方法实现
            direction = move(matrix, width, height, pointer, direction, clockwise);
        }

        // 矩阵填充完毕,按照正常的方式循环输出即可
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                System.out.printf(format, matrix[y][x]);
            }
            System.out.println();  // 完成一行后输出换行
        }
    }

    /**
     * 在矩阵中移动
     *
     * @param matrix    矩阵,用于判断前进方向的下一个位置是否已经填充了数字,如果是则转向
     * @param width     矩阵的宽
     * @param height    矩阵的高
     * @param pointer   指针的当前位置。调用本方法后里面的值会改变,除非方法返回 0
     * @param direction 指针当前移动的方向
     * @param clockwise 是否是要按顺时针方向转向
     *
     * @return 移动后的新方向(与原来的方向可能相同也可能不同)。如果无法再继续移动,则返回 0
     */
    private static int move(int[][] matrix, int width, int height, int[] pointer, int direction, boolean clockwise) {

        // 先尝试按照原来的方向移动到 newPointer
        int[] newPointer = moveDirectly(pointer, direction);

        // 检查 newPointer 是否合法,如果合法则将其赋值给 pointer 并保持原来的方向,方法完成
        if (isValid(newPointer, matrix, width, height)) {
            System.arraycopy(newPointer, 0, pointer, 0, 2);
            return direction;
        }

        // 进行转向,重新从 pointer 朝新的方向移动
        direction = turn(direction, clockwise);
        newPointer = moveDirectly(pointer, direction);

        // 检查 newPointer 是否合法(同前面一样)
        if (isValid(newPointer, matrix, width, height)) {
            System.arraycopy(newPointer, 0, pointer, 0, 2);
            return direction;
        }

        // 既无法前进也无法转向,那么无法继续移动。
        return 0;
    }

    // 判断矩阵中指定的位置是否可以填充
    private static boolean isValid(int[] newPointer, int[][] matrix, int width, int height) {

        // 位置不能超出矩阵范围
        if (newPointer[0] >= height
                || newPointer[0] < 0
                || newPointer[1] >= width
                || newPointer[1] < 0) {
            return false;
        }

        // 位置的内容应该为空
        if (matrix[newPointer[0]][newPointer[1]] != 0) {
            return false;
        }

        return true;
    }

    // 转向。根据我们对 direction 的定义,顺时针就是 +1,逆时针就是 -1
    private static int turn(int direction, boolean clockwise) {
        int newDirection = clockwise ? direction + 1 : direction - 1;

        if (newDirection > 4) {
            newDirection = 1;
        } else if (newDirection < 1) {
            newDirection = 4;
        }

        return newDirection;
    }

    /**
     * 朝指定的方向移动,并返回新的位置
     *
     * @param pointer   当前位置
     * @param direction 方向
     *
     * @return 新的位置
     */
    private static int[] moveDirectly(int[] pointer, int direction) {
        int y = pointer[0];
        int x = pointer[1];

        switch (direction) {
            case 1:
                return new int[]{y - 1, x};
            case 2:
                return new int[]{y, x + 1};
            case 3:
                return new int[]{y + 1, x};
            case 4:
                return new int[]{y, x - 1};
        }

        throw new IllegalArgumentException("方向不正确: " + direction);
    }
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

n*n阶矩阵逆时针输出

问题描述:n*n阶矩阵逆时针输出。 即: 输入:5 输出: 01 16 15 14 13 02 17 24 23 12 03 18 25 22 11 04 19 20 21 10 05...

剑指offer面试题:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。 输入一个矩阵如下:  1     2     3    4  5     6     7 &...

矩阵------顺时针打印矩阵+顺时针旋转矩阵+之字形打印矩阵(Java)

顺时针打印矩阵 题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打...

MySQL面试题目

2015年2月份面试一家上市公司,笔试中的题,没写这道题,一面的时候聊的挺嗨,吹牛逼说这题会需要时间,之后二面的时候面试官直接拿个mac过来让我写这道题,他在旁边看着,当时怎一个囧字了得。。。今天翻看...

java逆时针螺旋输出矩阵

import java.util.Scanner; /**  *@author Sun  * @since  * @version 1.0  *   **/ public class t...

java 输出回环数(螺旋矩阵)

以前见过,没做出来;那天论坛再见,灵感来了,太神奇了 复杂度好像为 o(n) 保存下来 public static void main(String[] args) { ...

打印回环数字矩阵

一个没有什么技术含量但是非常满足强迫症的面试题,打印出来看着很舒服。。。 打印回环数字矩阵,输入参数为边长n,例如n=4,求如下的回环矩阵: 1    2   3  4 12  13  14 ...

顺时针打印矩阵 按圈打印 java

顺时针打印矩阵 热度指数:1440时间限制:3秒空间限制:32768K 本题知识点: 模拟 数组  算法知识视频讲解 题目描述 对于一个矩阵,请设计一个算法从左上...

剑指Offer面试题20(Java版):顺时针打印矩阵

题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如:如果输入如下矩阵: 1,2,3,4 5,6,7,8 9,10,11,12 13,14,15,16 则依次打印出数字1,2,3,...

java实现 逆时针打印二维数组

记录一下,逆时针顺序打印二维数组(m行n列) package matrix; public class MatrixVisit { public static void main(St...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)