螺旋遍历和生成矩阵
class Matrix:
@staticmethod
def spiral_matrix(matrix: list) -> list:
"""
顺时针螺旋遍历矩阵
:param matrix: 矩阵,二维列表
:return: 遍历结果,一维列表
"""
if not matrix:
return
m, n = len(matrix), len(matrix[0])
try:
for i in range(m):
assert len(matrix[i]) == n
except AssertionError:
raise
res, left, right, up, down = [], 0, n - 1, 0, m - 1
# res长度 == m * n 则遍历结束
while len(res) < m * n:
# 从左向右遍历
if up <= down:
for j in range(left, right + 1):
res.append(matrix[up][j])
up += 1
# 从上向下遍历
if left <= right:
for i in range(up, down + 1):
res.append(matrix[i][right])
right -= 1
# 从右向左遍历
if up <= down:
for j in range(right, left-1, -1):
res.append(matrix[down][j])
down -= 1
# 从下向上遍历
if left <= right:
for i in range(down, up - 1, -1):
res.append(matrix[i][left])
left += 1
return res
@staticmethod
def generate_matrix(m: int, n: int) -> list:
"""
顺时针生成m*n矩阵,包含元素 1 ~ m*n 所有元素
:param m: 矩阵行
:param n: 矩阵列
:return: 矩阵,二维列表
"""
if m <= 0 or n <= 0:
return
# 不能用 [[None] * n] * m 初始化 这种方式每行是引用的同一地址空间,修改列会影响所有行
res = [[None for _ in range(n)] for _ in range(m)]
left, right, up, down = 0, n - 1, 0, m - 1
num = 1
while num <= m * n:
# 从左向右遍历
if up <= down:
for j in range(left, right + 1):
res[up][j] = num
num += 1
up += 1
# 从上向下遍历
if left <= right:
for i in range(up, down + 1):
res[i][right] = num
num += 1
right -= 1
# 从右向左遍历
if up <= down:
for j in range(right, left - 1, -1):
res[down][j] = num
num += 1
down -= 1
# 从下向上遍历
if left <= right:
for i in range(down, up - 1, -1):
res[i][left] = num
num += 1
left += 1
return res
if __name__ == '__main__':
mt = Matrix()
matrix_1 = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20]]
print(mt.spiral_matrix(matrix_1))
matrix_2 = mt.generate_matrix(5, 4)
print(matrix_2)
print(mt.spiral_matrix(matrix_2))
初始化矩阵:不能用[[None] * n] * m方式
实验:
res1 = [[None for _ in range(3)] for _ in range(2)]
for i in range(len(res1)):
print('{}方式:第{}行地址为{}'.format('[[None for _ in range(3)] for _ in range(2)]', i, id(res1[i])))
print('-----------------')
res2 = [[None] * 3] * 2
for i in range(len(res2)):
print('{}方式:第{}行地址为{}'.format('[[None] * 3] * 2', i, id(res2[i])))
输出:
[[None for _ in range(3)] for _ in range(2)]方式:第0行地址为4082224
[[None for _ in range(3)] for _ in range(2)]方式:第1行地址为14209192
-----------------
[[None] * 3] * 2方式:第0行地址为14209072
[[None] * 3] * 2方式:第1行地址为14209072
优化循环条件
class Matrix:
@staticmethod
def spiral_matrix(matrix: list) -> list:
"""
顺时针螺旋遍历矩阵
:param matrix: 矩阵,二维列表
:return: 遍历结果,一维列表
"""
if not matrix:
return
m, n = len(matrix), len(matrix[0])
try:
for i in range(m):
assert len(matrix[i]) == n
except AssertionError:
raise
res, left, right, up, down = list(), 0, n - 1, 0, m - 1
# 按层模拟遍历(一层一层剥离)
while left <= right and up <= down:
# 从左向右遍历up行
for j in range(left, right + 1):
res.append(matrix[up][j])
# 从上向下遍历right列
for i in range(up + 1, down + 1):
res.append(matrix[i][right])
if left < right and up < down:
# 从右向左遍历down行
for j in range(right - 1, left - 1, -1):
res.append(matrix[down][j])
# 从下向上遍历left列
for i in range(down - 1, up, -1):
res.append(matrix[i][left])
left, right, up, down = left + 1, right - 1, up + 1, down - 1
return res
@staticmethod
def generate_matrix(m: int, n: int) -> list:
"""
顺时针生成m*n矩阵,包含元素 1 ~ m*n 所有元素
:param m: 矩阵行
:param n: 矩阵列
:return: 矩阵,二维列表
"""
if m <= 0 or n <= 0:
return
# 不能用 [[None] * n] * m 初始化 这种方式每行是引用的同一地址空间,修改列会影响所有行
res = [[None for _ in range(n)] for _ in range(m)]
left, right, up, down = 0, n - 1, 0, m - 1
num = 1
while left <= right and up <= down:
# 从左向右遍历up行
for j in range(left, right + 1):
res[up][j] = num
num += 1
# 从上向下遍历right列
for i in range(up + 1, down + 1):
res[i][right] = num
num += 1
if left < right and up < down:
# 从右向左遍历down行
for j in range(right - 1, left - 1, -1):
res[down][j] = num
num += 1
# 从下向上遍历left列
for i in range(down - 1, up, -1):
res[i][left] = num
num += 1
left, right, up, down = left + 1, right - 1, up + 1, down - 1
return res