刷题地址:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路1: 直接动态模拟:
(1) 判断每个格子开始作为邮票左上角,右下角(StampHeight,StampWidth)下是否可以放置完整邮票,如果可以,将该邮票覆盖区域标记为2
(2) 如果全部遍历后仍有空格,则返回false
结果超时 。。。
class Solution:
def possibleToStamp(self, grid: List[List[int]], stampHeight: int, stampWidth: int) -> bool:
#如果超出范围则直接返回错误
height = len(grid)
width = len(grid[0])
def occupy(posx, posy):
if posx + stampHeight > height or posy + stampWidth > width:
return False
for i in range(posx, posx + stampHeight):
for j in range(posy, posy + stampWidth):
if grid[i][j] == 1:
return False
return True
def modify(posx, posy):
for i in range(posx, posx + stampHeight):
for j in range(posy, posy + stampWidth):
if grid[i][j] == 0:
grid[i][j] = 2
def check():
for i in range(height):
for j in range(width):
if grid[i][j] == 0:
return False
return True
for i in range(height):
for j in range(width):
if occupy(i, j):
modify(i, j)
return check()
改进方式1:在判断每个格子是否可以完全被覆盖,需要重复检测,利用二维前缀和快速判断该区域内是否都是空各子
class Solution:
def possibleToStamp(self, grid: List[List[int]], stampHeight: int, stampWidth: int) -> bool:
#如果超出范围则直接返回错误
height = len(grid)
width = len(grid[0])
def modify(posx, posy):
for i in range(posx, posx + stampHeight):
for j in range(posy, posy + stampWidth):
if grid[i][j] == 0:
grid[i][j] = 2
def check():
for i in range(height):
for j in range(width):
if grid[i][j] == 0:
return False
return True
#为方便处理,下标从1开始处理
preSum = [[0] * (width + 1) for _ in range(height+1)]
for i in range(1,height+1):
for j in range(1,width+1):
preSum[i][j] = preSum[i][j-1] + preSum[i-1][j] -preSum[i-1][j-1] + grid[i-1][j-1]
for i in range(height- stampHeight+1):
for j in range(width-stampWidth+1):
x = i + stampHeight -1
y = j + stampWidth -1
if preSum[x+1][y+1] - preSum[x+1][j] -preSum[i][y+1]+ preSum[i][j] == 0 :
modify(i, j)
return check()
仍然超时,继续改进
改进点2:如何快速判断空格是否都被邮票覆盖?
利用二维前缀和逆运算,(i,j)处贴邮票,从(i,j)到 (i+stampwidth -1,j+stampheight-1)数据量+1,计算diff(i,j) > 0 表示其被覆盖
diff(i,j)=diff(i,j)+diff(i−1,j)+diff(i,j−1)−diff(i−1,j−1)
class Solution:
def possibleToStamp(self, grid: List[List[int]], stampHeight: int, stampWidth: int) -> bool:
#如果超出范围则直接返回错误
height = len(grid)
width = len(grid[0])
def check():
for i in range(1,height+1):
for j in range(1,width+1):
diff[i][j] = diff[i][j] + diff[i-1][j] + diff[i][j-1] - diff[i-1][j-1]
if diff[i][j] == 0 and grid[i-1][j-1] == 0:
return False
return True
#为方便处理,下标从1开始处理
preSum = [[0] * (width + 2) for _ in range(height+2)]
diff = [[0] * (width + 2) for _ in range(height+2)]
for i in range(1,height+1):
for j in range(1,width+1):
preSum[i][j] = preSum[i][j-1] + preSum[i-1][j] -preSum[i-1][j-1] + grid[i-1][j-1]
for i in range(1,height- stampHeight+2):
for j in range(1,width-stampWidth+2):
x = i + stampHeight -1
y = j + stampWidth -1
if preSum[x][y] - preSum[x][j-1] -preSum[i-1][y]+ preSum[i-1][j-1] == 0 : #该区域都被0 覆盖
#使用差分将该区域内容进行覆盖
diff[i][j] = diff[i][j] + 1
diff[i][y+1] -= 1
diff[x+1][j] -= 1
diff[x+1][y+1] += 1
return check()