给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
示例:
输入:
[
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
]
输出: [1,2,4,7,5,3,6,8,9]
解释:
说明:
- 给定矩阵中的元素总数不会超过 100000 。
思路:
由观察可以得知,一共有两种走法,向右上方走和向左下方走。(第一个元素也是向右上方走)
再由二维数组的特性可以得知,向右上方走实际上等于 x -= 1, y += 1, 向左下方走实际上等于 x+= 1, y -= 1。
然后再判断什么时候应该转弯:
1. 当向右上方走的时候,有两种情况会造成碰壁,因而需要转弯,
CASE 1: 碰到上方的壁 (x无法再 - 1),但还没碰到右方的壁(y可以+1)
在这种情况下,下一步的坐标为y += 1, 比如上方示例图里的 1 -》 2。
CASE 2: 碰到右方的壁 (y 不能 + 1)
在这种情况下,下一步的坐标为x += 1, 比如示例图里的 3 -》 6
2. 向左下方走同理:
CASE1. 碰左壁但未碰下壁:x += 1
CSSE2. 碰下壁:y += 1
class Solution(object):
def findDiagonalOrder(self, matrix):
"""
:type matrix: List[List[int]]
:rtype: List[int]
"""
# 向右上方走,x -= 1, y += 1
# 向左下角走,x += 1, y -= 1
m = len(matrix)
if not m :
return []
n = len(matrix[0])
if not n :
return []
cnt = 0
x, y = 0, 0
res = list()
direction = "right"
while(cnt < m * n):
cnt += 1
# print direction, x, y, matrix[x][y]
res.append(matrix[x][y])
if direction == "right":#向右上方走
if x >= 1 and y < n - 1: # 不用调换方向
x -= 1
y += 1
continue
else:
direction = "left" #调换方向
if x == 0 and y < n - 1: #碰上壁
y += 1
elif y == n - 1: #碰右壁
x += 1
else: # 向左下方走
if x < m - 1 and y >= 1: # 不用调换方向
x += 1
y -= 1
continue
else:
direction = "right" #调换方向
if x == m - 1: # 碰下壁
y += 1
elif y == 0 and x < m - 1: #碰左壁
x += 1
# print res
return res
第二种思路:
我们也可以把每条对角线找出来,对角线的起点是第一列和最后一行。
然后记得隔一条对角线要翻转一次。
时间复杂度:O(MN)
空间复杂度:O(M +N)
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
if not mat or not mat[0]:
return []
m, n = len(mat), len(mat[0])
cors = [(i, 0) for i in range(m)] + [(m - 1, j) for j in range(1, n)]
res = []
reverse = -1
for i, j in cors:
diagonal = []
while 0 <= i < m and 0 <= j < n:
diagonal.append(mat[i][j])
i -= 1
j += 1
if reverse == 1:
diagonal = diagonal[::-1]
res.append(diagonal)
reverse = -reverse
return sum(res, [])