leetcode 1001 网格照明

388 阅读2分钟
 * @param {number} N
 * @param {number[][]} lamps
 * @param {number[][]} queries
 * @return {number[]}
 * 首先理解清楚题意: 任何一盏灯, 都能照亮穿过它的水平、垂直、左上到右下(135度角,主   
 对角线)线、右上到左下(45度角, 副对角线)线这四条线途经的任意格子, 但是每次查询, 只   
 会关掉包括被查询点在内离它最近的这四条线经过的9个格子里的灯。
 * 要看某个格子亮不亮, 那就看经过这个格子的四条线有没有途经亮着灯的格子(自己也算)。我   
 们发现,同一条垂直线上的格子水平坐标(x)相同, 同一  
 条水平线上的格子纵坐标(y)相同;同一条45度角线上的格子x + y相同,同一条135度角线上的  
 格子x - y相同;四种类别里每一种类别内不是同一条线上的格子,值一定不同。
 * 所以我们初始时只需要分别统计网格内这四类线(每一类线都有多条不同的线)每一条线有多  
 少盏灯亮着,然后没查询一次先根据统计信息判断被查询的格子亮不亮,然后再在四类线条统计  
 信息里面减去要熄灭的灯  
 就行;每查询一次就进行一次先判断亮不亮、再灭灯的操作,一次进行就行了。
 * 注意了:网格最多有10 ** 9 格, 我们用到的最大数是 2 * (10 ** 9) - 1,js最大整数是  
 2 ** 53次方, 是没有数值溢出的
 * */
    // 坐标水平最大值是 10 ** 9 - 1
const rowLen = 10 ** 9
var gridIllumination = function(N, lamps, queries) {
    // y
    const rowCounts = new Map()
    // x
    const colCounts = new Map()
    const deg45Counts = new Map()
    const deg135Counts = new Map()
    // 统计每盏灯的位置上, 有灯的格子才进行关灯操作,没灯的格子不能进行管等操作
    const lampPosition = new Set()
    // 统计每条线上有多少盏灯
    for(let lamp of lamps) {
        mapAddOne(rowCounts, lamp[0])
        mapAddOne(colCounts, lamp[1])
        mapAddOne(deg45Counts, lamp[0] + lamp[1])
        mapAddOne(deg135Counts, lamp[0] - lamp[1])
        lampPosition.add(lamp[0] * rowLen + lamp[1])
    }
    // 计算结果
    const ans = new Array(queries.length)
    for(let i = 0; i < queries.length; i++) {
        const q = queries[i]
        const deg45 = q[0] + q[1]
        const deg135 = q[0] - q[1]
        if(mapHas(rowCounts, q[0]) || mapHas(colCounts, q[1]) || mapHas(deg45Counts, deg45) || mapHas(deg135Counts, deg135)) {
            ans[i] = 1
            closeLamp(rowCounts, colCounts, deg45Counts, deg135Counts, q[0], q[1], lampPosition)
        } else ans[i] = 0
    }
    return ans
};

function mapAddOne(map, key) {
    if(map.has(key)) {
        map.set(key, map.get(key) + 1)
    } else map.set(key, 1)
}

function mapHas(map, key) {
    if(map.has(key) && (map.get(key) > 0)) {
        return true
    } else return false
}

function mapReduceOne(map, key) {
    if(map.has(key)) {
        map.set(key, map.get(key) - 1)
    }
}

function closeLamp(rowCounts, colCounts, deg45Counts, deg135Counts, row, col, lampPosition) {
    for(let r = -1; r <=1; r++) {
        for(let c = -1; c <= 1; c++) {
            const r2 = row + r
            const c2 = col + c
            // 不能越界
            if((r2 < 0) || (r2 >= rowLen) || (c2 < 0) ||(c2 >= rowLen)) continue
            // 有灯才关灯, 没灯就不能关
            const lamp = r2 * rowLen + c2
            if(lampPosition.has(lamp)) {
                lampPosition.delete(lamp)
                mapReduceOne(rowCounts, r2)
                mapReduceOne(colCounts, c2)
                mapReduceOne(deg45Counts, r2 + c2)
                mapReduceOne(deg135Counts, r2 - c2)
            }
        }
    }
}```