《剑指offer》【顺时针打印矩阵】(python版)

题目描述:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 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.
思路:螺旋访问数组是常见的一类题目,还可以变形为螺旋生成n维数组。这类题目思路都是相同的,主要是控制访问每行每列的边界。
  考虑:用两个变量xnum,ynum分别对访问列方向、行方向上前进步数的限制。ynum初始值为列数, xnum初始值为行数-1。打印具体过程如下:
  当行列方向可前进步数均不为0并且输出列表长度小于原矩阵元素个数时,循环以下四个方向:
  →:行方向的打印,坐标y值步进,可前进步数为yum。
  ↓:列方向的打印,坐标x值步进,可前进步数为xnum。
  走过半圈之后,ynum和xnum都减1,这是很显然的。
  ←:行方向的打印,坐标y值后退,为了保证与→ 方向数据不重合,需要加上xnum>=0的判断,这个判断的意思是上边界与下边界之间有间隔,因为如果此时只剩一行数据,那么意味着列方向可前进步数为0,即上一步的xnum = 0 - 1 = -1
  ↑:行方向的打印,坐标x值后退,为了保证与↓ 方向数据不重合,需要加上ynum>=0的判断,这个判断的意思是左边界与右边界之间有间隔,同上

def printMatrix(self, matrix):
        # write code here
        out = []
        # m, n分别表示行、列数
        m = len(matrix)
        if m == 0:
            return out
        n = len(matrix[0])
        # x,y表示当前访问到第x行第y列
        x = 0
        y = -1
        # xnum, ynum限制当前访问方向上的元素个数
        ynum = n
        xnum = m - 1
        while len(out) < m * n and ynum >= 0 and xnum >= 0:
            for i in range(ynum):
                y += 1
                out.append(matrix[x][y])       
            for i in range(xnum):
                x += 1
                out.append(matrix[x][y])
            ynum -= 1
            xnum -= 1
            if xnum >= 0:
                for i in range(ynum):
                    y -= 1
                    out.append(matrix[x][y])
                ynum -= 1
            if ynum >= 0:
                for i in range(xnum):
                    x -= 1
                    out.append(matrix[x][y])
                xnum -= 1
        return out

还有几种不同的思路,比如计算需要循环的圈数,按照圈数控制行列的边界,但是原理上还是相同的,这里不再进行实现。

其实使用python语言,还有更为简便的方式,不需要小心的计算每行每列元素剩余个数,也不需要计算圈数,但是缺点是改变了原矩阵。
实现代码如下,原理利用了python数组本身的性质。需要注意的是对于上下边界只需要判断原数组是否为空即可, 但是左右边界需要判断数组中是否存在空数组

    def printMatrix(self, matrix):
        out = []
        while matrix:
            # 上边界即为数组的第一个子数组
            out += matrix.pop(0)
            # 如果这里仅判断if matrix,那么对于测试数组例[[1],[2],[3]],循环后变成了[[],[]],matrix不为空
            if matrix and matrix[0]:
                # 右边界即为数组每一项的最后一个元素
                for row in matrix:
                    out.append(row.pop())
            # 下边界即为数组最后一个子数组的逆序排列
            if matrix:
                out += matrix.pop()[::-1]
            if matrix and matrix[0]:
                # 左边界即为数组从尾到头的每一项子数组的第一个元素
                for row in matrix[::-1]:
                    out.append(row.pop(0))
        return out

猜你喜欢

转载自blog.csdn.net/qq_20141867/article/details/80902980
今日推荐