力扣-二维数组的变换
- 对于原地工作的算法,很重要的一个思想是,用标志位来表示我们进行的操作,例如289生命游戏,用一个标志来表示更改前后的两种状态,这样既保留了之前的数据,又保留了更改后的数据。
- 还可以用相反数来标记该数,但其实不改变他所含有的数据,例如442重复的数据。
重塑矩阵(566)
思路: 先判断 重塑后的矩阵和原来矩阵的元素是否相等,不相等则返回原矩阵。
随后遍历原矩阵,用 count 来记录是否遍历完一个 c 的长度,也就是重塑后矩阵的列数,当count==c 时,将刚刚遍历的元素作为重塑后的第一行,再令 count = 0,重复 上述操作,即可得到重塑后的每一行。
class Solution:
def matrixReshape(self, mat: List[List[int]], r: int, c: int) -> List[List[int]]:
h = len(mat)
w = len(mat[0])
result=[]
if r*c!=h*w:
return mat
temp=[]
count=0
for i in range(h):
for j in range(w):
temp.append(mat[i][j])
count+=1
if count==c:
result.append(temp)
temp=[]
count=0
return result
旋转图像(48)
思路: 以示例1为例,修改(0,0)的位置需要改变其余三个位置的值(0,2)、(2,2)、(2,0),只需要修改(0,0)和(0,1)就可以更新完全部位置(也就是进行了旋转)。
第一行从第一个起,到倒数第二个
第二行从第二个其,到倒数第三个
以此类推
总共执行 n//2 行
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
n=len(matrix)
p=0
k=n-1
for i in range(n//2):
for j in range(p,k):
x=i
y=j
pre=matrix[x][y]
for q in range(4):
matrix[y][n-x-1],pre=pre,matrix[y][n-x-1]
x,y=y,n-x-1
p+=1
k-=1
矩阵置零(73)
思路一: 用set集合来记录需要置零的行和列,最后统一进行置零,时间复杂度为 O(m+n)。
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
m=len(matrix)
n=len(matrix[0])
row=set()
col=set()
for i in range(m):
for j in range(n):
if matrix[i][j]==0:
row.add(i)
col.add(j)
for y in row:
for j in range(n):
matrix[y][j]=0
for x in col:
for i in range(m):
matrix[i][x]=0
思路二: 用第一行和第一列来记录该行和该列有没有0,然后还需要用两个标志来记录第一行和第一列是否有0,因为第一行有0,需要把该行都置零,第一列同理。
除去第一行第一列进行一个遍历,matrix[i][j]=0,则置第一行和第一列的标志为0。
最后再除去第一行第一列进行一个遍历,如果该行或者该列标志为0,则该位置置0。
最后再对第一行和第一列进行判断是否置零。
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
m = len(matrix)
n = len(matrix[0])
row_flag=False
col_flag=False
# 找第一行是否有0,以便后面处理第一行
for i in range(n):
if matrix[0][i]==0:
row_flag=True
# 找第一列是否有0,以便后面处理第一列
for j in range(m):
if matrix[j][0]==0:
col_flag=True
for i in range(1,m):
for j in range(1,n):
if matrix[i][j]==0:
matrix[i][0]=matrix[0][j]=0
# 置零操作
for i in range(1,m):
for j in range(1,n):
if matrix[i][0]==0 or matrix[0][j]==0:
matrix[i][j]=0
if row_flag==True:
for j in range(n):
matrix[0][j]=0
if col_flag==True:
for i in range(m):
matrix[i][0]=0
生命游戏 (289)
方法一思路: 将原数组进行一个复制,然后再复制的数组上去判断规则,在原数组上进行更改。
class Solution:
def gameOfLife(self, board: List[List[int]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
m=len(board)
n=len(board[0])
result=[[0 for i in range(n)] for j in range(m)]
for i in range(m):
for j in range(n):
result[i][j]=board[i][j]
for i in range(m):
for j in range(n):
live=0
for x in range(i-1,i+2):
for y in range(j-1,j+2):
if 0<=x<m and 0<=y<n and result[x][y]==1:
live+=1
if result[i][j]==1:
live-=1
if result[i][j]==1 and live<2:
board[i][j]=0
elif result[i][j]==1 and (live==2 or live==3):
board[i][j]=1
elif result[i][j]==1 and live>3:
board[i][j]=0
elif result[i][j]==0 and live==3:
board[i][j]=1
方法二思路: 在原数组上进行更改,更改时用 2 来表示细胞从1到0,用 -1表示细胞从0变1,这样既能表示修改前的值又能表示修改后的值。
class Solution:
def gameOfLife(self, board: List[List[int]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
m=len(board)
n=len(board[0])
# 更新每一个元素
for i in range(m):
for j in range(n):
# 统计每一个元素周围存活的细胞
live=0
for x in range(i-1,i+2):
for y in range(j-1,j+2):
if 0<=x<m and 0<=y<n and (board[x][y]==1 or board[x][y]==-1):
live+=1
# 排除该细胞本身
if board[i][j]==1:
live-=1
# 根据符合标志(0->1为2,1->0 为-1)更新数组
if board[i][j]==1 and live<2:
board[i][j]=-1
elif board[i][j]==1 and (live==2 or live==3):
pass
elif board[i][j]==1 and live>3:
board[i][j]=-1
elif board[i][j]==0 and live==3:
board[i][j]=2
# 再遍历一次数组将2和-1分别再转为1和0
for i in range(m):
for j in range(n):
if board[i][j]==2:
board[i][j]=1
elif board[i][j]==-1:
board[i][j]=0