开启我的LeetCode刷题日记:1001. 网格照明

142 阅读3分钟

「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战

编程世界总是离不了算法

最近在看框架源码时,会有很多算法的实现逻辑,有时候会感到吃力

于是决定蹭着假期,加强算法和数据结构相关的知识

那怎么提升呢?

其实我知道算法这东西没有捷径,多写多练才能提升,于是我开启我的LeetCode刷题之旅

第一阶段目标是:200道,每天12

为了不乱,本系列文章目录分为三部分:

  1. 今日题目:xxx
  2. 我的思路
  3. 代码实现

今天题目:1001. 网格照明

难度:困难

在大小为 n x n 的网格 grid 上,每个单元格都有一盏灯,最初灯都处于 关闭 状态。

给你一个由灯的位置组成的二维数组 lamps ,其中 lamps[i] = [rowi, coli] 表示 打开 位于 grid[rowi][coli] 的灯。即便同一盏灯可能在 lamps 中多次列出,不会影响这盏灯处于 打开 状态。

当一盏灯处于打开状态,它将会照亮 自身所在单元格 以及同一 行 、同一 列 和两条 对角线 上的 所有其他单元格 。

另给你一个二维数组 queries ,其中 queries[j] = [rowj, colj] 。对于第 j 个查询,如果单元格 [rowj, colj] 是被照亮的,则查询结果为 1 ,否则为 0 。在第 j 次查询之后 [按照查询的顺序] ,关闭 位于单元格 grid[rowj][colj] 上及相邻 8 个方向上(与单元格 grid[rowi][coli] 共享角或边)的任何灯。

返回一个整数数组 ans 作为答案, ans[j] 应等于第 j 次查询 queries[j] 的结果,1 表示照亮,0 表示未照亮。

我的思路

注意到 n 的范围会很大,无法创建这么大的空间。而灯泡的数量和 queries 的长度都在两万以内。

当一盏灯处于打开状态,它将会照亮 自身所在单元格 以及同一行 、同一列和两条对角线 上的 所有其他单元格 。

我们可以记录被灯照亮的行、列、撇、捺。行和列好处理,记录每个等的横坐标和纵坐标就可以了。而撇和捺可以用灯的横纵坐标的和与差来表示。

例如 (1,1) 位置的灯,它的捺对角线上所有位置的 x' - y' 都等于 1 - 1 = 0。而撇对角线上的所有位置的 x' + y' 都等于 1 + 1 = 2。可以利用这个信息来判断是否被灯照亮。

代码实现

**
 * @param {number} n
 * @param {number[][]} lamps
 * @param {number[][]} queries
 * @return {number[]}
 */
var gridIllumination = function(n, lamps, queries) {
    const rows = new Map()
    const cols = new Map()
    const left = new Map()
    const right = new Map()
    const lampPos = new Map()

    for (let [x, y] of lamps) {
        if (!lampPos.has(`${x},${y}`)) {
            lampPos.set(`${x},${y}`, true)
            rows.set(x, (rows.get(x) || 0) + 1)
            cols.set(y, (cols.get(y) || 0) + 1)
            left.set(x + y, (left.get(x + y) || 0) + 1)
            right.set(x - y, (right.get(x - y) || 0) + 1)
        }
    }

    const dirs = [        [-1, -1],
        [-1, 0],
        [-1, 1],
        [0, -1],
        [0, 0],
        [0, 1],
        [1, -1],
        [1, 0],
        [1, 1],
    ]
    return queries.map(([x, y]) => {
        const on = (rows.get(x) > 0 || cols.get(y) > 0 || left.get(x + y) > 0 || right.get(x - y) > 0)
        for (const [dx, dy] of dirs) {
            const nx = x + dx
            const ny = y + dy

            if (lampPos.has(`${nx},${ny}`)) {
                lampPos.delete(`${nx},${ny}`)
                rows.set(nx, rows.get(nx) - 1)
                cols.set(ny, cols.get(ny) - 1)
                left.set(nx + ny, left.get(nx + ny) - 1)
                right.set(nx - ny, right.get(nx - ny) - 1)
            }
        }
        return on
    })
};


总结

实现方式其实有很多,这里仅供参考~

由于刚开始刷题,也不知道从哪里刷好,如果前辈们有好的建议,希望不吝赐教,感谢🌹