1001. 网格照明(python3)/(困难)

暴力解法不可取,因为遍历数据导致时间与空间的浪费,出现运行超时等问题。

解题思路:

我们利用哈希表加快查找数据的效率。

先对数据进行去重处理(亮同一盏灯可能在 lamps 中多次列出,不会影响这盏灯处于 打开 状态。),然后利用哈希表来表示该灯泡是否被点亮。

r[i] 的值表示为这一行亮着的灯泡数,当我们点亮第 i 行灯泡时,直接 r[i] += 1,熄灭灯泡时 r[i] -= 1。

同理,列也可以用c[j]表示

反对角线上坐标的特点:x+y 在一条对角线上是一个恒定的数值

同理正对角线上的坐标特点是: x-y 在一条对角线上是一个恒定的数值

当某一行会被两个灯泡照亮时,r[i] = 3 (结果了三次 r[i] += 1)
那么只有三个灯泡都熄灭时,r[i] = 0,也就是结果三次 r[i] -= 1
因此,该点的8个方向上的值都为0时,说明这个灯泡是暗的
8个反向上只要有一个不为0,说明这个灯泡是亮的。

下面是该问题的具体解决代码:

from collections import defaultdict


class Solution:
    def gridIllumination(self, n: int, lamps: list[list[int]],
                         queries: list[list[int]]) -> list[int]:
        #         利用哈希表判断该灯是否会亮
        r, c, dia1, dia2 = defaultdict(int), defaultdict(int), defaultdict(int), defaultdict(int)

        # 去除重复的灯泡
        lamp = set()
        for x,y in lamps:
            if (x,y) not in lamp:
                lamp.add((x,y))
                # 构建哈希表
                r[x]+=1     #行
                c[y]+=1     #列
                dia1[x-y]+=1   #对角线
                dia2[x+y]+=1   #反对角线

        result = list()
        # 检查是否被照亮
        for x,y in queries:
            if r[x] or c[y] or dia1[x-y] or dia2[x+y]:
                result.append(1)
            else:
                result.append(0)
        #     删除四周的灯泡
            for i in [-1,0,1]:
                for j in [-1,0,1]:
                    nx = x+i
                    ny = y+j
                    # 判断该灯泡是否在lamp里面
                    if (nx,ny) in lamp:
                        # 更新哈希表
                        lamp.remove((nx,ny))
                        r[nx] -= 1  # 行
                        c[ny] -= 1  # 列
                        dia1[nx - ny] -= 1  # 对角线
                        dia2[nx + ny] -= 1  # 反对角线
        return result

知识点:

 有关defaultdict的用法:

 

注意事项:

代码中用集合存储被打开的灯(即 lamp=set() ),是因为集合基于哈希表实现,这使得它们能够在常数时间复杂度(O(1))内查找元素是否存在。相比之下,列表的查找操作需要遍历整个列表,其时间复杂度为O(n),其中n是列表中的元素数量。因此,当数据集较大时,集合的查找效率远高于列表。同理,除了查找操作外,集合还支持在常数时间复杂度内添加和删除元素,而列表是基于顺序表实现的,相比之下,列表的插入和删除操作(特别是在列表的开头或中间位置)可能需要移动多个元素,从而导致更高的时间复杂度。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值