算法思想一:按层模拟遍历
解题思路:
可以将矩阵看成若干层,首先打印最外层的元素,其次打印次外层的元素,直到打印最内层的元素。
对于每层,从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于 (top,left),右下角位于(bottom,right),按照如下顺序遍历当前层的元素。
1、从左到右遍历上侧元素,依次为(top,left) 到(top,right)。
2、从上到下遍历右侧元素,依次为(top+1,right) 到 (bottom,right)。
3、如果 left<right 且top<bottom,则从右到左遍历下侧元素,依次为(bottom,right−1) 到 (bottom,left+1),以及从下到上遍历左侧元素,依次为(bottom,left) 到(top+1,left)。
遍历完当前层的元素之后,将left 和top 分别增加 1,将 right 和 bottom 分别减少 11,进入下一层继续遍历,直到遍历完所有元素为止。
1、从左到右遍历上侧元素,依次为(top,left) 到(top,right)。
2、从上到下遍历右侧元素,依次为(top+1,right) 到 (bottom,right)。
3、如果 left<right 且top<bottom,则从右到左遍历下侧元素,依次为(bottom,right−1) 到 (bottom,left+1),以及从下到上遍历左侧元素,依次为(bottom,left) 到(top+1,left)。
遍历完当前层的元素之后,将left 和top 分别增加 1,将 right 和 bottom 分别减少 11,进入下一层继续遍历,直到遍历完所有元素为止。
图解:从左向右、从上向下、从右向左、从下向上
代码展示:
Python版本
# -*- coding:utf-8 -*- class Solution: # matrix类型为二维列表,需要返回列表 def printMatrix(self, matrix): # write code here if not matrix: return matrix # 返回列表 result = [] shang = 0 xia = len(matrix)-1 left = 0 right = len(matrix[0])-1 while True: # 左到右 for i in range(left, right+1): # 存储遍历结果 result.append(matrix[shang][i]) shang += 1 if shang > xia: break # 上到下 for i in range(shang, xia+1): result.append(matrix[i][right]) right -= 1 if left > right: break # 右到左 for i in range(right, left-1, -1): result.append(matrix[xia][i]) xia -= 1 if shang > xia: break # 下到上 for i in range(xia, shang-1, -1): result.append(matrix[i][left]) left += 1 if left > right: break return result
复杂度分析:
时间复杂度O(MN):其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
空间复杂度O(1):除了输出数组以外,空间复杂度是常数。
算法思想二:递归
解题思路:
递归的思想和非递归的思想相差不大,递归是首先打印最外层的元素,将内层的矩阵作为一个全新的矩阵进行递归。
对于每层,从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于 (top,left),右下角位于(bottom,right),按照如下顺序遍历当前层的元素。
1、从左到右遍历上侧元素,依次为(top,left) 到(top,right)。
2、从上到下遍历右侧元素,依次为(top+1,right) 到 (bottom,right)。
3、如果 left<right 且top<bottom,则从右到左遍历下侧元素,依次为(bottom,right−1) 到 (bottom,left+1),以及从下到上遍历左侧元素,依次为(bottom,left) 到(top+1,left)。
遍历完当前层的元素之后,将left 和top 分别增加 1,将 right 和 bottom 分别减少 11,进入下一次递归,直到遍历完所有元素为止。
1、从左到右遍历上侧元素,依次为(top,left) 到(top,right)。
2、从上到下遍历右侧元素,依次为(top+1,right) 到 (bottom,right)。
3、如果 left<right 且top<bottom,则从右到左遍历下侧元素,依次为(bottom,right−1) 到 (bottom,left+1),以及从下到上遍历左侧元素,依次为(bottom,left) 到(top+1,left)。
遍历完当前层的元素之后,将left 和top 分别增加 1,将 right 和 bottom 分别减少 11,进入下一次递归,直到遍历完所有元素为止。
图解:首先递归最外层,再递归第二层。。。。
代码展示:
JAVA版本
import java.util.ArrayList; public class Solution { ArrayList<Integer> res = new ArrayList<>(); public ArrayList<Integer> printMatrix(int [][] matrix) { if(matrix==null||matrix.length==0) return res; int m = matrix.length; int n = matrix[0].length; print(0, n-1, 0, m-1, matrix); return res; } public void print(int left, int right, int top, int bottom, int [][] matrix){ // 从左到右 for(int i = left; i <= right; i ++) res.add(matrix[top][i]); // 下一层 top ++; if(left > right || top > bottom) return; // 从上到下 for(int i = top; i <= bottom; i ++) res.add(matrix[i][right]); right --; if(left > right || top > bottom) return; // 从右到左 for(int i = right; i >= left; i --) res.add(matrix[bottom][i]); bottom --; if(left > right || top > bottom) return; // 从下到上 for(int i = bottom; i >= top; i --) res.add(matrix[i][left]); left ++; // 递归 print(left, right, top, bottom, matrix); } }
复杂度分析:
时间复杂度O(MN):其中 m 和 n 分别是输入矩阵的行数和列数。矩阵中的每个元素都要被访问一次。
空间复杂度O(1):除了输出数组以外,空间复杂度是常数。