题目
题目简化分析
一个0/1数组,判断每个元素周围一圈的和。并匹配题设规则,对各个元素进行更新。
- 必须是针对整个矩阵进行更新。即:下一个元素进行更新时,基于的是当前元素更新之前的值。
Insight
- 当作卷积进行处理。卷积核为[[1,1,1],[1,0,1],[1,1,1]],并对整个矩阵进行padding,以避免对边缘的判断。(思路很新,但运行速度较慢,内存占用较大)。代码
- 常规方法。对每个元素循环其周围元素的和,将结果与规则进行匹配,更新元素。在更新元素这块,有两种方法。
- 复制原矩阵,在进行运算时,使用原矩阵,更新时更新复制的矩阵,以满足对整个矩阵进行更新。代码
- 进行位操作,由于0/1是在第一bit,将更新后的参数放入第二个bit,循环结束后,再将矩阵的各个元素右移一位。双百C++方案
实现
代码
改写上方双百C++
class Solution(object):
def gameOfLife(self, board):
"""
:type board: List[List[int]]
:rtype: None Do not return anything, modify board in-place instead.
"""
r = len(board)
c = len(board[0])
if r <= 0 or c <= 0:
return [] //异常情况
dx = [-1,0,1,-1,1,-1,0,1]
dy = [-1,-1,-1,0,0,1,1,1]
for i in range(r):
for j in range(c):
sum = 0
for n in range(8):
ni = dx[n]+i
nj = dy[n]+j
if ((ni>=0 and ni<r) and (nj>=0 and nj<c)):
sum += (board[ni][nj] & 1) //位运算1
if board[i][j] == 1:
if sum == 3 or sum == 2:
board[i][j] |= 2 //位运算2
else:
if sum == 3:
board[i][j] |= 2 //位运算2
for i in range(r):
for j in range(c):
board[i][j] >>= 1 ////位运算3
return board
- 位运算1:即选择周围元素值的最后一位(因为更新的值被放入的第二位,所以此时
board[ni][nj]
的值并不是初始值。如[[0,1,1][1,1,1]]这个矩阵在0被更新后,变成了[[2(0b10),1,1],[1,1,1]],在对[0,1]位置的1进行操作时,如果不用board[ni][nj] & 1
这个位运算,sum
就会等于6,而实际上sum
为4。 - 位运算2:匹配规则将更新后的参数记入第二位。
- 位运算3:将第二位的值移到第一位,返回结果。