leetcode
leetcode 2401 ~ 2450
黑格子的数目

黑格子的数目

难度:

标签:

题目描述

You are given two integers m and n representing the dimensions of a 0-indexed m x n grid.

You are also given a 0-indexed 2D integer matrix coordinates, where coordinates[i] = [x, y] indicates that the cell with coordinates [x, y] is colored black. All cells in the grid that do not appear in coordinates are white.

A block is defined as a 2 x 2 submatrix of the grid. More formally, a block with cell [x, y] as its top-left corner where 0 <= x < m - 1 and 0 <= y < n - 1 contains the coordinates [x, y], [x + 1, y], [x, y + 1], and [x + 1, y + 1].

Return a 0-indexed integer array arr of size 5 such that arr[i] is the number of blocks that contains exactly i black cells.

 

Example 1:

Input: m = 3, n = 3, coordinates = [[0,0]]
Output: [3,1,0,0,0]
Explanation: The grid looks like this:

There is only 1 block with one black cell, and it is the block starting with cell [0,0].
The other 3 blocks start with cells [0,1], [1,0] and [1,1]. They all have zero black cells. 
Thus, we return [3,1,0,0,0]. 

Example 2:

Input: m = 3, n = 3, coordinates = [[0,0],[1,1],[0,2]]
Output: [0,2,2,0,0]
Explanation: The grid looks like this:

There are 2 blocks with two black cells (the ones starting with cell coordinates [0,0] and [0,1]).
The other 2 blocks have starting cell coordinates of [1,0] and [1,1]. They both have 1 black cell.
Therefore, we return [0,2,2,0,0].

 

Constraints:

  • 2 <= m <= 105
  • 2 <= n <= 105
  • 0 <= coordinates.length <= 104
  • coordinates[i].length == 2
  • 0 <= coordinates[i][0] < m
  • 0 <= coordinates[i][1] < n
  • It is guaranteed that coordinates contains pairwise distinct coordinates.

代码结果

运行时间: 427 ms, 内存: 20.2 MB


/*
 * 题目思路:
 * 1. 使用Java Stream API来简化代码结构。
 * 2. 创建一个数组result,长度为5,用来保存恰好包含0到4个黑色格子的块的数量。
 * 3. 遍历coordinates数组,对于每个黑色格子的坐标,将其影响的所有可能包含该格子的2x2块的黑色格子数增加1。
 * 4. 使用stream来统计每个2x2块的黑色格子数,最终统计每个黑色格子数的块的数量。
 */

import java.util.*;
import java.util.stream.Collectors;

public class Solution {
    public int[] countBlackBlocks(int m, int n, int[][] coordinates) {
        int[] result = new int[5];
        Map<String, Integer> blockCount = new HashMap<>();

        Arrays.stream(coordinates).forEach(coord -> {
            int x = coord[0], y = coord[1];
            for (int i = Math.max(0, x - 1); i <= Math.min(x, m - 2); i++) {
                for (int j = Math.max(0, y - 1); j <= Math.min(y, n - 2); j++) {
                    String key = i + "," + j;
                    blockCount.put(key, blockCount.getOrDefault(key, 0) + 1);
                }
            }
        });

        blockCount.values().forEach(count -> result[count]++);

        int totalBlocks = (m - 1) * (n - 1);
        result[0] = totalBlocks - Arrays.stream(result).sum() + result[0];

        return result;
    }
}

解释

方法:

该题解首先使用一个集合s来记录所有黑色格子的坐标,以便于后续判断一个格子是否为黑色。接着,遍历所有的黑色格子坐标,并对每个黑色格子坐标进行四种情况的检查:1) 当前格子作为2x2子矩阵左上角;2) 当前格子作为2x2子矩阵右上角;3) 当前格子作为2x2子矩阵左下角;4) 当前格子作为2x2子矩阵右下角。对于每一种情况,根据黑色格子的存在与否统计每个子矩阵中黑色格子的数量,并更新结果数组ans。最后,通过总2x2子矩阵数量减去包含1个及以上黑色格子的子矩阵的数量,来计算完全由白色格子组成的子矩阵的数量。

时间复杂度:

O(k)

空间复杂度:

O(k)

代码细节讲解

🦆
题解中提到使用集合s来检查格子是否为黑色,这种方法在什么情况下可能导致性能瓶颈?
使用集合s检查格子是否为黑色的方法,虽然提供了O(1)时间复杂度的平均查询效率,但在某些特定情况下可能会导致性能瓶颈。当输入的黑色格子坐标数量非常大时,尤其是接近整个网格大小的时候,集合的维护(插入和查询操作)可能会消耗较多的时间和空间。此外,Python中集合的性能还受到负载因子和哈希冲突的影响,当哈希表的负载因子过高或哈希函数产生了较多的冲突时,集合操作的效率会下降。
🦆
在分别检查格子是否可以作为2x2子矩阵的四个角的逻辑中,是否有重复计算的可能性?如果有,如何优化以减少重复计算?
题解中确实存在重复计算的可能性,尤其是当同一个黑色格子被多次考虑为不同2x2子矩阵角的情况时。例如,一个黑色格子在作为一个子矩阵的左上角被计算后,可能还会作为相邻子矩阵的右上角或左下角等再次被计算。为了减少重复计算,可以通过只从特定方向(如只考虑每个格子作为2x2子矩阵的左上角)来进行计数,这样可以确保每个子矩阵只被计算一次,然后根据需要调整其他角的计数逻辑,确保所有情况被正确计算而不重复。
🦆
题解中对于ans数组的更新逻辑似乎存在某些分支不更新ans数组的情况,这是否意味着存在漏计的风险?
是的,题解中的逻辑确实存在不更新ans数组的情况,这主要发生在某些边界或角落的格子无法形成完整的2x2子矩阵时。例如,如果一个黑色格子位于网格的边界上,那么它可能无法作为2x2子矩阵的某些角,这导致这些情况下ans数组不被更新。这种情况下,如果没有适当的处理,确实存在漏计的风险。为了避免漏计,需要确保对所有可能形成的2x2子矩阵进行全面的检查和计数,特别是对于边界和角落的格子,要根据其位置调整计数逻辑,确保所有可能的情况都被正确计算。

相关问题