【问题标题】:Binary Matrix find all cells with distance k二元矩阵找到距离为 k 的所有单元格
【发布时间】:2021-07-02 18:50:09
【问题描述】:

我有一个带有01 的二进制矩阵,并且给定整数K >=0。现在我想找到与值为1 的单元格最大距离为K 的所有可能单元格,并将它们标记为某个字母“x”。

单元格 A[5][2] 和 A[1][4] 之间的距离为 |1-5|+|4-2|=6。

例子:

一个 8x8 矩阵和 K = 2,在 (2,2)(6,6) 处具有值 1 的单元格

0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0

输出:

0 0 x 0 0 0 0 0
0 x x x 0 0 0 0
x x 1 x x 0 0 0
0 x x x 0 0 0 0
0 0 x 0 0 0 x 0
0 0 0 0 0 x x x
0 0 0 0 x x 1 x
0 0 0 0 0 x x x

这是我正在尝试的逻辑:

找到 1 的单元格位置,并找到从行 -k 到给定列的 +k 的所有单元格。类似地,查找具有给定行和列的所有单元格,范围从 -k+k。所以对于上面的例子,对于(2,2),基于我的逻辑的单元格是(0,2),(1,2),(2,2),(3,2),(4,2)然后( 2,0) , (2,1) , (2,2) , (3,2), (4,2)。

但我无法理解如何获取 (2,2) 周围的剩余单元格,即 (1,1), (1,3) 和 (3,1) , (3,3)。

Matrix is of size m rows and n cells in range 1 to 500
K range is 1 to 1000

【问题讨论】:

  • 也许你可以把它想象成一个面具。如果你用 x 和 y 替换所有数字,IMO 会更容易看到你需要做什么
  • 用数学术语给出一个解决方案,如果你从感兴趣的位置减去迭代索引,那么绝对值不应超过radius(作为整数)。这基本上是一个曼哈顿距离计算。
  • 你了解性能吗?
  • @oleg.cherednik,我现在添加了 K 和矩阵的范围

标签: java algorithm


【解决方案1】:

如果您不关心性能,解决方案可能很简单。

public static void markAllCellsWithDistance(char[][] matrix, int k) {
    for (int row = 0; row < matrix.length; row++)
        for (int col = 0; col < matrix[row].length; col++)
            if (matrix[row][col] == '1')
                markCells(matrix, k, row, col);
}

private static void markCells(char[][] matrix, int k, int row1, int col1) {
    for (int row2 = 0; row2 < matrix.length; row2++)
        for (int col2 = 0; col2 < matrix[row2].length; col2++)
            if (matrix[row2][col2] == '0' && distance(row1, col1, row2, col2) <= k)
                matrix[row2][col2] = 'x';
}

private static int distance(int row1, int col1, int row2, int col2) {
    return Math.abs(row1 - row2) + Math.abs(col1 - col2);
}

【讨论】:

  • 谢谢,如果性能也很重要,那么替代方法是什么。
  • 如果性能是实际的,那么你必须从1开始,绕过这个单元格。
【解决方案2】:

试试这个。

static void markNeighbors(char[][] matrix, int k) {
    int rows = matrix.length, cols = matrix[0].length;
    new Object() {

        void set(int x, int y) {
            for (int r = Math.max(0, x - k), rr = Math.min(rows, x + k + 1); r < rr; ++r)
                for (int s = k - Math.abs(r - x), c = Math.max(0, y - s), cc = Math.min(cols, y + s + 1); c < cc; ++c)
                    if (matrix[r][c] == '0')
                        matrix[r][c] = 'x';
        }

        void find() {
            for (int i = 0; i < rows; ++i)
                for (int j = 0; j < cols; ++j)
                    if (matrix[i][j] == '1')
                        set(i, j);
        }
    }.find();
}

char[][] matrix = {
    {'0', '0', '0', '0', '0', '0', '0', '0'},
    {'0', '0', '0', '0', '0', '0', '0', '0'},
    {'0', '0', '1', '0', '0', '0', '0', '0'},
    {'0', '0', '0', '0', '0', '0', '0', '0'},
    {'0', '0', '0', '0', '0', '0', '0', '0'},
    {'0', '0', '0', '0', '0', '0', '0', '0'},
    {'0', '0', '0', '0', '0', '0', '1', '0'},
    {'0', '0', '0', '0', '0', '0', '0', '0'},
};

markNeighbors(matrix, 2);

for (char[] row : matrix)
    System.out.println(Arrays.toString(row));

输出:

[0, 0, x, 0, 0, 0, 0, 0]
[0, x, x, x, 0, 0, 0, 0]
[x, x, 1, x, x, 0, 0, 0]
[0, x, x, x, 0, 0, 0, 0]
[0, 0, x, 0, 0, 0, x, 0]
[0, 0, 0, 0, 0, x, x, x]
[0, 0, 0, 0, x, x, 1, x]
[0, 0, 0, 0, 0, x, x, x]

【讨论】:

  • 所有rowcol 检查都可以在各自的for 可能节省大量if 之前完成。
【解决方案3】:

如果你将每组 x-es 分解为四个三角形:一个三角形由位于中心 1 上方的k x-es 和右侧的所有 x-es 组成;剩下的三个三角形是围绕 1 旋转第一个三角形;

你意识到三角形的每一行都比前一行短一个“x”;

然后出现算法:

for a,b being a position of '1'
    for i in 1 .. k
        for j in 1 .. (k - i + 1)
            set 'x' at (a+j, b-i)
            set 'x' at (a+i, b+j)
            set 'x' at (a-j, b+i)
            set 'x' at (a-i, b+j)

请记住根据数组范围检查结果坐标,不要在另一个 '1' 所在的位置设置 'x'。

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 2020-02-09
    • 2021-09-23
    • 1970-01-01
    相关资源
    最近更新 更多