【问题标题】:Finding coordinates on a grid (2D array)在网格上查找坐标(二维数组)
【发布时间】:2018-09-17 05:17:29
【问题描述】:

我目前正在尝试解决我在白板模拟面试中未能解决的问题。我被卡住了几次。任何帮助表示赞赏。

问题的措辞是这样的:

给定一个带有灯坐标数组的 NxN 网格。每盏灯都为其 x 轴上的每个方格、y 轴上的每个方格以及对角线上的每个方格提供照明(想想国际象棋中的皇后)。给定一个查询坐​​标数组,确定该点是否被照亮。

问题是在检查查询时,与该查询相邻或位于该查询上的所有灯都会关闭。如果您访问一个坐标/单元格,请关闭该坐标或相邻的所有灯。如果两个单元格共享相同的边或角,则它们是相邻的。

  • 写一个函数checkLampIllumination(N, lamps, queries)
  • N : 网格大小
  • lamps : 一盏灯的坐标
  • queries : 检查网格上的坐标是否点亮

给我的测试用例是:

N = 8

lamps = [
    [1,6],
    [5,6],
    [7,3],
    [3,2]
]

queries = [
    [4,4],
    [6,6],
    [8,1],
    [3,2],
    [2,3]
]

输出:

['DARK','LIGHT','DARK','DARK','LIGHT']

第二个测试用例:

checkLampIllumination(8, [[4,3],[4,4]], [[3,4],[7,6]])

N = 8

lamps = [
    [4,3],
    [4,4]
]

queries = [
    [3,4],
    [7,6]
]

输出:

['DARK','LIGHT']

这是我目前的尝试。我认为当前的解决方案只是创建了网格。我真的不知道从这里去哪里。

const checkLampIllumination=(N, lamps, queries) => {
    var gridNxN = []
    var row = []
    for (var i = 1; i < 100; i++) {
        if (i.toString().indexOf('0') !== -1) {
            row.push(i)
            gridNxN.push(row)
            row = []
        } else {
            row.push(i)
        }
    }
}

【问题讨论】:

    标签: javascript arrays matrix depth-first-search breadth-first-search


    【解决方案1】:

    只是为了可视化灯和查询,如果需要,您可以使用pixel art generator

    我首先创建一个辅助函数isAdjacent 来检查两个点是否相邻。然后,遍历每个查询(目标方块),并检查是否有任何灯照亮目标。问题归结为检查:

    • 灯不相邻,且至少满足以下一项:

    • 灯要么具有相同的 X 坐标,要么

    • 相同的 Y 坐标,或

    • 它们在同一对角线上,可以通过查看灯与目标 X 坐标之间的差值是否等于灯与目标 Y 坐标之间的差值来检查。

    将其放入代码中,您会得到:

    let lamp = [
      [1, 6],
      [5, 6],
      [7, 3],
      [3, 2]
    ];
    const queries = [
      [4, 4],
      [6, 6],
      [8, 1],
      [3, 2],
      [2, 3]
    ]
    
    const isAdjacent = (x1, y1, x2, y2) => Math.abs(x2 - x1) < 2 && Math.abs(y2 - y1) < 2;
    queries.forEach(([checkX, checkY]) => {
      const thisSquareIlluminated = lamp.some(([lampX, lampY]) => (
        !isAdjacent(checkX, checkY, lampX, lampY) && (
          lampX === checkX
          || lampY === checkY
          || Math.abs(lampX - checkX) === Math.abs(lampY - checkY)
        )
      ));
      console.log(thisSquareIlluminated ? 'LIGHT' : 'DARK');
    });

    我不建议事先构建照明方块,因为这样,如果给出查询,您将不知道具有照明的特定方块是否仅由于相邻灯而具有照明,至少在没有遍历所有照明的情况下不会再次点亮灯 - 最好在选择查询后只遍历它们一次。

    请注意,N = 8 输入不会在任何地方使用 - 这是一条红鲱鱼,除非您还需要检查灯/查询是否也在板上的有效空间中。

    【讨论】:

    • 原来的措辞对我来说不是很清楚,但你的 isAdjacent 助手不认为对角线上的单元格是相邻的(例如 isAdjacent(1,1,2,2) 返回 false)我不知道这是否是一个问题尽管。此外,虽然我真的不确定如何阅读它,但我认为 catch 部分意味着网格不是无状态的(即,一旦你通过检查它关闭了灯,它应该保持关闭 => 改变lamp 数组),例如,如果有最后一个 [1, 6] 查询,它应该返回 Dark。但再一次,我真的不确定我的阅读......
    • 从您的代码和小提琴开始,它开始变得更有意义,尤其是对角线的可视化。我认为 N 开始发挥作用来制作网格。例如,NxN 将创建一个 8 行 9 列的网格。他们可能给了 N,因为 N 可能更小或更大。但我不太确定
    • @TrueLife 但他们没有说明在电网外输入的情况下应该发生什么。所以网格大小没有什么意义。
    • @Kaiido 是的,我没有想到那种极端情况
    【解决方案2】:

    由于我们目前没有接受采访,所以我决定保持代码不紧凑,以便更容易理解。如果你愿意,你可以缩短它。我喜欢这类问题,所以我花时间解决它。

    我还更新了视觉网格。现在您可以看到网格的变化状态。

    var lamps = [
        [1,6],
        [5,6],
        [7,3],
        [3,2]
    ];
    
    var queries = [
        [4,4],
        [6,6],
        [8,1],
        [3,2],
        [2,3]
    ];
    
    /* ==================== VISUAL GRID ==================== */
    
    function arrayFlatten(array) {
        var result = [];
        array.forEach(function (item) {
            if (item instanceof Array) {
                result = result.concat(arrayFlatten(item));
            } else {
                result.push(item);
            }
        });
        return result;
    }
    
    function createGrid(lamps, queries) {
        var grid = document.createElement("table");
        grid.classList.add("grid");
        var gridSize = Math.max.apply(null, arrayFlatten([lamps, queries])) + 1;
        
        document.body.appendChild(grid);
        
        // create cells
        for (var i = 0; i < gridSize; i++) {
            var row = document.createElement("tr");
            for (var j = 0; j < gridSize; j++) {
                var cell = document.createElement("td");
                row.appendChild(cell);
            }
            grid.appendChild(row);
        }
        
        // add lamps
        lamps.forEach(lamp => grid.rows[lamp[1]].cells[lamp[0]].classList.add("lamp"));
    
        var illuminatedRows = Array.from(new Set(lamps.map(([lampX, lampY]) => lampY)));
        var illuminatedCols = Array.from(new Set(lamps.map(([lampX, lampY]) => lampX)));
        illuminatedRows.sort();
        illuminatedCols.sort();
    
        // add lights
        // horizontal
        for (var i = 0; i < grid.rows.length; i++) {
            if (illuminatedRows.includes(i)) {
                Array.from(grid.rows[i].cells).forEach(cell => cell.classList.add("horizontal-light"));
            }
        }
        // vertical
        for (var i = 0; i < grid.rows.length; i++) {
            for (var j = 0; j < grid.rows[i].cells.length; j++) {
                if (illuminatedCols.includes(j)) {
                    grid.rows[i].cells[j].classList.add("vertical-light");
                }
            }
        }
        // diagonal
        for (var i = 0; i < grid.rows.length; i++) {
            for (var j = 0; j < grid.rows[i].cells.length; j++) {
                var x = j;
                var y = i;
                lamps.forEach(function (lamp) {
                    if (isDiagonal(lamp[0], lamp[1], x, y)) {
                        grid.rows[i].cells[j].classList.add("diagonal-light");
                    }
                });
            }
        }
        
    }
    
    createGrid(lamps, queries);
    
    /* ==================== CALCULATION ==================== */
    
    function isHorizontal(y1, y2) {
        return y1 == y2;
    }
    
    function isVertical(x1, x2) {
        return x1 == x2;
    }
    
    function isDiagonal(x1, y1, x2, y2) {
        return Math.abs(x1 - x2) == Math.abs(y1 - y2);
    }
    
    function isIlluminated(queryX, queryY, lampX, lampY) {
        return isHorizontal(queryY, lampY) || isVertical(queryX, lampX) || isDiagonal(queryX, queryY, lampX, lampY);
    }
    
    function isAdjacent(x1, y1, x2, y2) {
        return Math.abs(x2 - x1) < 2 && Math.abs(y2 - y1) < 2
    }
    
    // check every lamp for each query
    function checkLamps(lamps, queryX, queryY) {
        // store checks for each lamp for a query
        var checks = [];
        // loop every lamp
        for (var i = lamps.length - 1; i >= 0; i--) {
            var lampX = lamps[i][0];
            var lampY = lamps[i][1];
            // check if the target cell is adjacent to the current lamp
            if (isAdjacent(queryX, queryY, lampX, lampY)) {
                console.log("Query (" + [queryX, queryY].join() + ") is adjacent to lamp (" + [lampX, lampY].join() + "). Removing this lamp.");
                // lamp is adjacent; remove it
                lamps.splice(i, 1);
                // create a grid with the new state (for visual purposes)
                createGrid(lamps, queries);
                // skip this lamp
                continue;
            } else {
                // storing the check for the current lamp
                checks.push(isIlluminated(queryX, queryY, lampX, lampY));
            }
        }
        // if all checks are false, it's dark
        // if there's even a single true, that means the cell is illuminated by a lamp
        if (checks.includes(true)) {
            console.log("(" + [queryX, queryY].join() + ") is LIGHT");
        } else {
            console.log("(" + [queryX, queryY].join() + ") is DARK");
        }
    }
    
    function checkLampIllumination(lamps, queries) {
        // create a local copy of lamps because it'll (might) mutate
        var lamps = lamps.slice();
        // loop queries
        queries.forEach(([queryX, queryY]) => checkLamps(lamps, queryX, queryY));
    }
    
    checkLampIllumination(lamps, queries);
    .grid {
        background-color: black;
        border-collapse: collapse;
        margin-right: 1em;
        float: left;
    }
    .grid td {
        width: 25px;
        height: 25px;
        border: 1px solid hsl(0, 0%, 50%);
    }
    .grid td.horizontal-light,
    .grid td.vertical-light,
    .grid td.diagonal-light {
        background-color: hsla(0, 0%, 80%, .33);
    }
    .grid td.horizontal-light.vertical-light,
    .grid td.horizontal-light.diagonal-light,
    .grid td.vertical-light.diagonal-light {
        background-color: hsla(0, 0%, 80%, .45);
    }
    .grid td.horizontal-light.vertical-light.diagonal-light {
        background-color: hsla(0, 0%, 80%, .6);
    }
    .grid td.lamp {
        background-color: hsl(0, 0%, 100%) !important;
    }

    【讨论】:

    • 我有点困惑。您在哪里尝试确定该点是否被照亮?
    • @TrueLife 对不起。昨天我忙碌了一天。没有时间真正研究问题,只是创建了一个视觉网格。我现在已经更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    • 2021-06-26
    • 2022-01-16
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多