LeetCode 54. Spiral Matrix &&剑指OFFER29,顺时针打印矩阵

参考资料:左程云算法课

54. Spiral Matrix
Given an m x n matrix, return all elements of the matrix in spiral order.

 

Example 1:


Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]

思路:用矩阵的左上角点和右下角点确定一个框(最外层),然后一圈一圈的地打印,先打印最外层,借助矩阵的左上角点和右下角点的坐标分别对角线方向向内收缩一步,可以到达新的框(也就是次外层),再打印次外层,……
注:要考虑到 最后一圈可能出现的情况,即
最后一圈可能是空;可能是一个数,可能是一行数,也可能是一列数。

class Solution {
    public List<Integer> spiralOrder1(int[][] m) {
	List<Integer> ans = new ArrayList<>();
		if(m==null||m.length==0||m[0]==null||m[0].length==0)
		{
			return ans;
		}
		
		int a=0;
		int b=0;
		int c = m.length-1;
		int d=m[0].length-1;
		
		while(a<=c && b<=d)
		{
			addEdge(m,a++,b++,c--,d--,ans);
		}
		return ans;
	}
	public static void addEdge(int[][] m, int a,int b, int c, int d, List<Integer> ans)
	{
		int curR=a;
		int curC=b;
        if(a==c)
        {
            for(int i=b;i<=d;i++)
            {
                ans.add(m[a][i]);
            }
            return;
        }
        if(b==d)
        {
            for(int i=a;i<=c;i++  )
            {
                ans.add(m[i][b]);
            }
            return;
        }
		for(;curC<d;curC++)
		{
			ans.add(m[curR][curC]);
			
		}
		for(;curR<c;curR++)
		{
			ans.add(m[curR][curC]);
		}
		for(;curC>b;curC--)
		{
			ans.add(m[curR][curC]);
			
		}
		for(;curR>a;curR--)
		{
			ans.add(m[curR][curC]);
		}

	}

}

上面是老师写的;
下面是自己写的;思路差不多

   public List<Integer> spiralOrder(int[][] ma) {
          int m = ma.length;
          int n = ma[0].length;
          List<Integer> prep = new ArrayList<>();

          int r1=0,c1=0;
          int r2=m-1,c2=n-1;
          while(r1<=r2 && c1<=c2) // ,,
          {
              spiral(ma,r1,c1,r2,c2,prep);
              r1++;
              c1++;
              r2--;
              c2--;
          }
         return prep;
      }
      void spiral(int[][] ma, int r1, int c1, int r2, int c2, List<Integer> prep)
      {
          if(r1==r2 && c1==c2)
          {
              prep.add(ma[r1][c1]);
              return;
          }else if(r1==r2)
          {
              for(int i=c1;i<=c2;i++)
              {
                  prep.add(ma[r1][i]);
              }
              return;
          }else if(c1==c2)
          {
              for(int i=r1;i<=r2;i++)
              {
                  prep.add(ma[i][c1]);
              }
              return;
          }

          int r=r1;
          int c=c1;
          while(c<c2) // right
          {
              prep.add(ma[r][c]);
              c++;
          }
          // r1,c2
          while(r<r2)
          {
              prep.add(ma[r][c]);
              r++;
          }
          // r2,c2
          while(c>c1)
          {
              prep.add(ma[r][c]);
              c--;
          }
          // r2,c1
          while(r>r1)
          {
              prep.add(ma[r][c]);
              r--;
          }

      }

官网给出的迭代解法

public int[] spiralOrder(int[][] matrix) {
       if(matrix==null||matrix.length==0||matrix[0].length==0){
           return new int[0];
       }
       int rows = matrix.length,cols = matrix[0].length;
    //    int left=0,right=cols-1,up=0,bottom=rows-1;
       int index=0;
       int[] res = new int[rows*cols];
        int x1=0,y1=0,x2=rows-1,y2=cols-1;
        while(x1<=x2 && y1<=y2){
            for(int j=y1;j<=y2;j++){
                res[index++]=matrix[x1][j];
            }
            for(int i=x1+1;i<=x2;i++){
                res[index++]=matrix[i][y2];
            }
            if(x1<x2 && y1<y2){ // !! 这个判断条件很重要,如果y1==y2那么就没必要向左遍历记录框的下边界了
                 for(int j=y2-1;j>=y1;j--){
                res[index++]=matrix[x2][j];
                }
                for(int i=x2-1;i>x1;i--){
                    res[index++]=matrix[i][y1];
                }
            }
           
            x1++;
            y1++;
            x2--;
            y2--;
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值