数据结构与算法_剑指Offer20_顺时针打印矩阵_JAVA实现

2020.05.06

题目

输入一个矩阵,按照从外向里以顺时针的顺序依次扫印出每一个数字。
点击链接

解题思路

把打印一圈分为四步:第一步从左到右打印一行,第二步从上到下打印一列,第三步从右到左打印一行,第四步从下到上打印一列。每一步我们根据起始坐标和终止坐标用一个循环就能打印出一行或者一列。
但是,我们会遇到一些情况,就是随着一圈又一圈的读,最后退化到 图4.4 的情况 , 打印一圈分别只需要三步、两步甚至只有一步。
因此我们要仔细分析打印时每一步的前提条件:
1、第一步总是需要的, 因为打印一圈至少有一步。
2、第二步的前提条件:是终止行号大于起始行号(原因:如果只有一行,那么就不用第二步了)。
3、第三步的前提条件:是圈内至少有两行两列,也就是说除了要求终止行号大于起始行号之外,同时终止列号大于起始列号
4、同理第三步,第四步的前提条件:是至少有三行两列,因此除了要求终止行号比起始行号至少大2,同时终止列号大于起始列号
在这里插入图片描述

package offer20;

public class Test {
    public static void printCycle(int[][] numberArray) {
        if(numberArray == null || numberArray.length == 0) {
            System.out.println("入参不合法");
            return;
        }
        
        //初始化行的起点
        int x = 0;
        //初始化列的起点
        int y = 0;
        //行起点值不大于(numberArray.length-1)/2
        //列起点值不大于(numberArray[0].length-1)/2
        while (x <= (numberArray.length-1)/2 && y <= (numberArray[0].length-1)/2) {
            print(numberArray,x,y);
            x++;
            y++;
        }
    }
    
    public static void print(int[][] numberArray,int x,int y) {
        int rows = numberArray.length - 1;
        int cols = numberArray[0].length - 1;
                
        for(int i = y;i <= cols - y;i++ ) {
            System.out.print(numberArray[x][i] + " ");
        }
        //注意我们要排除第一行最后一个打印过的
        //总行数 - 起始行数  > 起始行数;总行数 - 起始行数 表示最后面的行下标;下面同理;
        if(rows - x > x) {
            for(int i = x + 1 ;i <= rows - x;i++ ) {
                System.out.print(numberArray[i][cols - y] + " ");
            }
        }
        
        if( rows - x > x && cols - y > y ) {
            for(int i = cols-y-1;i >= x; i--) {
                System.out.print(numberArray[rows - x][i] + " ");
            }
        }
        
        if( rows - x > x && cols - y > y + 1 ) {
            //防止打印这一圈第一个值
            for(int i = rows-x-1;i > x;i-- ) {
                System.out.print(numberArray[i][y] + " ");
            }
        }
    }
    
    public static void main(String[] args) {
        int[][] numbers1 = {
                {1, 2, 3, 4, 5},
                {16, 17, 18, 19, 6},
                {15, 24, 25, 20, 7},
                {14, 23, 22, 21, 8},
                {13, 12, 11, 10, 9},
        };
        printCycle(numbers1);
        System.out.println();

        int[][] numbers2 = {
                {1, 2, 3, 4, 5, 6, 7, 8},
                {22, 23, 24, 25, 26, 27, 28, 9},
                {21, 36, 37, 38, 39, 40, 29, 10},
                {20, 35, 34, 33, 32, 31, 30, 11},
                {19, 18, 17, 16, 15, 14, 13, 12},

        };
        printCycle(numbers2);
        System.out.println();


        int[][] numbers3 = {
                {1, 2, 3, 4, 5, 6, 7, 8}
        };
        printCycle(numbers3);
        System.out.println();

        int[][] numbers4 = {
                {1, 2, 3, 4, 5, 6, 7, 8},
                {16, 15, 14, 13, 12, 11, 10, 9}
        };
        printCycle(numbers4);
        System.out.println();


        int[][] numbers5 = {
                {1},
                {2},
                {3},
                {4},
                {5},
                {6},
                {7},
                {8}
        };
        printCycle(numbers5);
        System.out.println();

        int[][] numbers6 = {
                {0, 1},
                {15, 2},
                {14, 3},
                {13, 4},
                {12, 5},
                {11, 6},
                {10, 7},
                {9, 8}
        };
        printCycle(numbers6);
        System.out.println();


        int[][] numbers7 = {
                {1, 2},
                {4, 3}
        };
        printCycle(numbers7);
        System.out.println();

        int[][] numbers8 = {
                {1}
        };
        printCycle(numbers8);
        System.out.println();

        // 0个元素的数组
        printCycle(new int[][]{{}});
        // 空数组
        printCycle(null);
    }
}


我写的时候也错了好几次,行遍历时要想列变化,列遍历要想着行变化,注意边界且四个部分不要重复读值,希望对正在阅读这篇文章的你有所帮助。

运行结果

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值