剑指Offer--顺时针打印矩阵问题

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

题目分析

这个题目看起来比较简单,但是当你真正去做的时候,很麻烦,亲身体验一把你就懂什么感受了。

主要的考察点在于控制顺时针的方向、行变化还是列变化、列变化的时候变化的范围是多少。这些都是需要考虑的,此外,更加需要注意的点是这个矩阵M*N的矩阵,程序中如果依赖于M和N的值的话,记得要分别的单独考虑一下。


实现思路

通过观察M==N的时候的矩阵的遍历过程,得出一部分规律。

比如{{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}对于这个矩阵而言,在顺时针遍历的过程中,每一个单项(一行或者一列)的数目分别为4,3,3,2,2,1,1。你会看到这里是有些规律可循的,这里的数字变化的非常规律,那么我想到的方法是,通过这个矩阵的行和列的值来确定一个数组,这个数组中就存储每一个项(一行或者一列)在遍历的时候要遍历变量的个数。记住每次的个数后也就是说就已经确定了遍历该矩阵的步骤,以上面的那个4*4的矩阵而言,其遍历的过程中,横向的遍历4个元素(行索引不变,列索引递增),纵向的遍历3个元素(行索引递增,列索引不变为上次递增后的结果),然后横向遍历3个元素(行索引不变,列索引要递减)......

这里已经确定了整个矩阵遍历的过程(遍历几次,每次遍历几个元素),但是还不知道每次遍历的这几个元素是递增的还是递减的,是行索引还是列的索引。

这里需要定义一个递增还是递减的变量、一个行索引用于记录整个遍历过程中行的索引的变化情况、一个列索引用于记录整个遍历过程中列的索引的变化情况。

注意一点:根据上面的分析,也可以去发现M*N的矩阵,当M>N的情况存在时,这个数组如何计算每一步的遍历个数。也应该考虑到当M<N的情况存在的时候,这个数组如何计算每一步的遍历个数。


public class PrintMatrix {

	public static void main(String[] args) {
		
		int [][] matrix = new int[][]{{1},{2},{3},{4}};
		ArrayList<Integer> list = printMatrix(matrix);
		System.out.println(list);
	}
	
	public static ArrayList<Integer> printMatrix(int [][] matrix) {
	       
        if(matrix.length == 0) {
            return null;
        }
        int count = 0;
        int countH = matrix.length;
        int countV = matrix[0].length;
        int[] nums = null;
        if(countH == countV) {
        	
        	nums = new int[1+(countH - 1) * 2];
        } else if(countH > countV) {
        	nums = new int[countV * 2];
        	
        } else {
        	
        	nums = new int[(countH < countV ? countH : countV) * 2 - 1];
        }
        for(int i = 0; i < nums.length; i++) {
        	if(i % 2 == 1) {
        		countH = countH - 1;
        		nums[i] = countH;
        	}
            if(i % 2 == 0) {
            	nums[i] = countV;
            	countV = countV - 1;
            }
        }
        
        int order = 0;
        int countI = 0;
        int countJ = 0;
        
        ArrayList<Integer> resultList = new ArrayList<Integer>();
        
        for(int j = 0; j < nums.length; j ++) {
            
            
            for(int k = nums[j]; k > 0; k --) {
                
                // 递增
                if(count % 2 == 0) {
                    
                    // 列递增
                    if(order == 0) {
                        
                    	if(count > 0 && k >= 1) {
                    		countJ++;
                    	}
                    	
                        resultList.add(matrix[countI][countJ]);
                        if(count == 0 && k > 1) {
                        	countJ++;
                        }
                        //System.out.print(matrix[countI][countJ++] + ",");
                    // 行递增
                    } else if(order == 1) {
                    	if(k >= 1) {
                        	countI++;
                        }
                        resultList.add(matrix[countI][countJ]);
                        
                        //System.out.print(matrix[countI++][countJ] + ",");
                    }
                    
                // 递减
                } else if(count % 2 == 1) {
                    
                    // 列递减
                    if(order == 0) {
                    	
                    	if(k >= 1) {
                        	countJ--;
                        }
                        resultList.add(matrix[countI][countJ]);
                        
                        //System.out.print(matrix[countI][countJ--] + ",");
                    
                    // 行递减
                    } else if(order == 1) {
                        
                    	if(k >= 1) {
                        	countI--;
                        }
                        resultList.add(matrix[countI][countJ]);
                        
                        //System.out.print(matrix[countI--][countJ] + ",");
                    }
                }
                
                
            }
            if(j % 2 == 1) {
            	count ++;
            }
            order = 1 - order;
        }
        return resultList;
        
    }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值