[LEETCODE day1] [系列] 贴邮票

刷题地址:力扣(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()

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值