2024.5.3力扣刷题记录-数组篇记录7

文章介绍了三种IT技术相关的问题:使用二维前缀和进行图片平滑、区间加法II的解决方案以及甲板上的战舰模拟计数方法。两种平滑器算法分别基于前缀和和模拟计算,而区间加法II涉及数学原理和最小重叠区域的求解。
摘要由CSDN通过智能技术生成

目录

一、661. 图片平滑器

1.二维前缀和

2.模拟

二、598. 区间加法 II

数学

三、419. 甲板上的战舰

模拟,一次扫描


一、661. 图片平滑器

1.二维前缀和

cnt求法参考题解(. - 力扣(LeetCode))。

class Solution:
    def imageSmoother(self, img: List[List[int]]) -> List[List[int]]:
        # 二维前缀和
        # 时复O(m * n),空复O(m * n)
        m, n = len(img), len(img[0])    # m * n
        # pad = 2
        for i in range(m):
            img[i] = [0, 0] + img[i] + [0, 0]
        '''
        # 错误写法
        pad = [[0] * (n + 4) for _ in range(2)]
        img = pad + img + pad
        会导致两头关联在同一数组上,值一起改变
        '''
        img = [[0] * (n + 4) for _ in range(2)] + img + [[0] * (n + 4) for _ in range(2)]
        m += 4
        n += 4
        # 求前缀和
        for i in range(2, m):
            for j in range(2, n):
                img[i][j] += img[i][j - 1] + img[i - 1][j] - img[i - 1][j - 1]
        # 对前缀和数组求平均值
        newImg = [[0] * (n - 4) for _ in range(m - 4)]
        for i in range(2, m - 2):
            for j in range(2, n - 2):
                total = img[i + 1][j + 1] - img[i - 2][j + 1] - img[i + 1][j - 2] + img[i - 2][j - 2]
                a, b = max(i - 1, 2), max(j - 1, 2)
                c, d = min(i + 1, m - 3), min(j + 1, n - 3)
                cnt = (c - a + 1) * (d - b + 1)
                newImg[i - 2][j - 2] = total // cnt
        # # 处理掉pad
        # img = img[2:-2]
        # for i in range(len(img)):
        #     img[i] = img[i][2:-2]
        return newImg

2.模拟

class Solution:
    def imageSmoother(self, img: List[List[int]]) -> List[List[int]]:
        # 模拟
        # 时复O(m * n * (C ^ 2)),空复O(m * n)
        m, n = len(img), len(img[0])    # m * n
        newImg = [[0] * n for _ in range(m)]
        for i in range(m):
            for j in range(n):
                total, cnt = 0, 0
                for x in range(max(i - 1, 0), min(i + 1, m - 1) + 1):
                    for y in range(max(j - 1, 0), min(j + 1, n - 1) + 1):
                        total += img[x][y]
                        cnt += 1
                newImg[i][j] = total // cnt
        return newImg

二、598. 区间加法 II

数学

class Solution:
    def maxCount(self, m: int, n: int, ops: List[List[int]]) -> int:
        # 数学
        # 求最小重叠区域
        '''
        原理:二维前缀和
        差分数组元素全为0
        # 二维前缀和
        if not ops:
            return m * n
        # 差分数组
        diff = [[0] * n for _ in range(m)]
        for x, y in ops:
            diff[x - 1][y - 1] += 1
        # 寻找
        cntX, cntY = m, n
        for i in range(m):
            for j in range(n):
                if diff[i][j] != 0:
                    # 最小重叠区域的个数即为最大元素的个数
                    cntX = min(cntX, i + 1)
                    cntY = min(cntY, j + 1)
        return cntX * cntY
        本质上ops出现的位置即为重叠区域
        即不用使用差分数组,直接求最小区域即可
        '''
        cntX, cntY = m, n
        for x, y in ops:
            cntX = min(cntX, x)
            cntY = min(cntY, y)
        return cntX * cntY

三、419. 甲板上的战舰

模拟,一次扫描

class Solution:
    def countBattleships(self, board: List[List[str]]) -> int:
        # 模拟,一次扫描
        # 时复O(m * n),空复O(1)
        cnt = 0
        m, n = len(board), len(board[0])
        for i in range(m):
            for j in range(n):
                ship = board[i][j]
                if ship == '.':
                    continue
                if (i == 0 or board[i - 1][j] == '.') and (j == 0 or board[i][j - 1] == '.'):
                    # 取决于左边和上面是不是'X'
                    cnt += 1
        return cnt

感谢你看到这里!一起加油吧!

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值