1. 二维数组
二维数组是一种结构较为特殊的数组,其数组的每个元素都是数组,即“数组的数组”。二维数组本质上仍然是一个一维数组。二维数组又称为矩阵,行列数相等的矩阵称为方阵。类似一维数组,计算机会在内存中申请申请一段连续 的空间来存储二维数组。
在实际中,通常使用二维数据处理矩阵类相关问题,包括矩阵旋转、对角线遍历,以及对子矩阵的操作等。对于数据科学而言,对二维数组甚至多维数组的处理更是重中之重。其中Matlab和众多的python科学计算库(numpy、pandas等)都对二维数组(或高维数组)的处理提供了最大的便利。
2. 例题实战
867. 转置矩阵[简单]
说明:
给定一个矩阵 A, 返回 A 的转置矩阵。
矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。
示例1:
输入: [[1,2,3],[4,5,6],[7,8,9]]
输出: [[1,4,7],[2,5,8],[3,6,9]]
示例2:
输入:[[1,2,3],[4,5,6]]
输出:[[1,4],[2,5],[3,6]]
解答:
1.按照题意,构造转置矩阵赋值即可
2.使用内置函数zip
# 1.直接赋值
class Solution:
def transpose(self, A: List[List[int]]) -> List[List[int]]:
m, n = len(A), len(A[0])
trans = [[0]*m for i in range(n)]
for i in range(m):
for j in range(n):
trans[j][i] = A[i][j]
return trans
# 2.内置函数
class Solution:
def transpose(self, A: List[List[int]]) -> List[List[int]]:
return [list(arr) for arr in zip(*A)]
注释:
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。
# zip 方法在 Python 2 和 Python 3 中的不同:
#在 Python 2.x zip() 返回的是一个列表,Python3.x 返回对象
a = [1, 2, 3]
b = [4, 5, 6]
c = [7, 8, 9]
d = zip(a,b,c)
d, list(d)
(, [(1, 4, 7), (2, 5, 8), (3, 6, 9)])
# *zip() 解压
a, b, c = list(zip(*zip(a,b,c)))
a, b, c
((1, 2, 3), (4, 5, 6), (7, 8, 9))
867. 零矩阵[中等] 说明:
编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。
示例1:
输入:[[1,1,1],
[1,0,1],
[1,1,1]]
输出:[[1,0,1],
[0,0,0],
[1,0,1]]
解答:
- 按照题意,找到零元素,标记下标索引,分别将行列索引存储在两个列表里。要注意的的是in-place要求在原数组上改动。时间复杂度O(mn)
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
row, col = [], []
if not matrix:
return None
m, n = len(matrix), len(matrix[0])
for i in range(m):
for j in range(n):
if matrix[i][j] == 0:
row.append(i)
col.append(j)
# elimate the same index
row = set(row)
col = set(col)
# process row
for i in row:
for j in range(n):
matrix[i][j] = 0
# process col
for j in col:
for i in range(m):
matrix[i][j] = 0
498. 对角线遍历[中等]
说明:
给定一个含有 M x N 个元素的矩阵(M 行,N 列),请以对角线遍历的顺序返回这个矩阵中的所有元素,对角线遍历如下图所示。
示例:
输入:[[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]]
输出: [1,2,4,7,5,3,6,8,9]
解答1:
- 遍历每个对角线的元素,外循环对角线最大的长度。每条对角线的下标索引和相等。难点在于索引的判断,防止下标越界。最后按照奇偶逆序连接即可。
class Solution:
def findDiagonalOrder(self, matrix: List[List[int]]) -> List[int]:
if not matrix:
return []
M, N = len(matrix), len(matrix[0])
res, tmp = [], []
for i in range(M+N-1):
tmp.clear()
# key import, not suquare matrix ,the location of element index
r, c = 0 if i -1
else i-N+
1, i
if i -1
else N
-1
while r and c >
-1:
tmp.append(matrix[r][c])
r += 1
c -= 1 if i % 2 == 0:
res.extend(tmp[:: -1]) else:
res.extend(tmp) return res
注释:
下标索引的确定,如下图。当行小于列(M>N)时行以下标r=0开始,以行数截止;当行大于列时,循环次数大于列数即i>N-1,行数以下标r=i-N+1开始,,同理可以分析列的索引变化
解答2:模拟法
类似矩阵迷宫模拟两种规则,往右上方 i -= 1, j += 1; 往左下方 i += 1,j -= 1 数组边界判断:
- 往右上方 1 触碰上边界,未触碰右边界j += 1, i = i 2 触碰右边界,i += 1, j = j
- 往左下方 1 触碰左边界,未触碰右边界i += 1, j = j 2 触碰下边界,j += 1 , i = i
class Solution:
def findDiagonalOrder(self, matrix):
if not matrix or not matrix[0]:
return []
M, N = len(matrix), len(matrix[0])
matrix_num = M * N
count = 0
i, j = 0, 0
result = []
direction = "up"
while (count count += 1
result.append(matrix[i][j])
# 向右上方向走
if direction == "up":
# 无需调换方向的条件(1.i>0 碰到上边界前, 2jif i > 0 and j 1:
i -= 1
j += 1
continue
else:
direction = "down"
# 碰到上边界:1 --> 2
if i == 0 and j 1
:
j += 1 # 碰到右边界:3 --> 6 elif j == N - 1:
i += 1 # 向左下方向走 else: # 无需调换方向的条件(1.i 0 碰到右边界前) if i 1 and y > 0:
i += 1
j -= 1 continue else:
direction = "up" # 碰左边界:4 --> 7 if j == 0 and x 1:
i += 1 # 碰下边界:8 --> 9 elif i == M - 1 :
y += 1 return result
参考链接:
1 https://leetcode-cn.com/leetbook/read/array-and-string/cuxq3/
2 https://leetcode-cn.com/problems/diagonal-traverse/solution/dui-jiao-xian-bian-li-by-leetcode/ 3 https://leetcode-cn.com/problems/diagonal-traverse/solution/zui-zhi-bai-de-xie - END -编辑:flybird7