如何获得由公共数据包围的矩阵位置?

时间:2017-02-28 07:32:44

标签: java matrix

我在Java中有一个定义的矩阵

int[][] a={
    {0,0,0,0,0,0},
    {0,0,0,1,0,0},
    {0,1,1,0,1,0},
    {1,0,0,0,0,1},
    {0,1,0,1,0,1},
    {0,0,1,0,1,0}
};

所以我想知道矩阵上的哪些位置被“1”值组成的线包围,即值为“0”的位置组,好像“1”是不规则图形的周长,在其周边区域内的“0”值(在这种情况下:a [2] [3],a [3] [1],a [3] [2],a [3] [3],a [ 3] [4],a [4] [2]和[4] [4])。

如何自动获得这些职位?

2 个答案:

答案 0 :(得分:0)

执行所需操作的一种方法是使用flood fill,不填充对角线。这对您自己没有帮助,但您可以使用一些非零值填充连接到数组边缘的所有区域。数组中剩余的零将是您渴望的元素。

以下是洪水填充的简单实现:

import java.util.ArrayDeque;
import java.awt.Point;  // This is probably superfluous, an int[] with two elements would do fine here too

public class Test
{
    private static int[][] a = new int[][] {
        {0, 0, 0, 0, 0, 0},
        {0, 0, 0, 1, 0, 0},
        {0, 1, 1 ,0, 1, 0},
        {1, 0, 0, 0, 0, 1},
        {0, 1, 0, 1, 0, 1},
        {0, 0, 1, 0, 1, 0}
    };

    /*
     * Applies flood fills all elements accessible from array[row][col] with
     * value. If the element at (row, col) is already value, this method does
     * nothing.
     */
    private static void floodFill(int[][] array, int row, int col, int value)
    {
        int oldValue = array[row][col];
        if(oldValue == value)
            return;
        ArrayDeque<Point> queue = new ArrayDeque<>();
        queue.add(new Point(col, row));
        while(queue.size() > 0) {
            // Technically, removeLast would be more efficient, especially
            // since the order does not matter, but this is just an example
            Point point = queue.pop();
            int r = point.y;
            int c = point.x;
            array[r][c] = value;

            if(r > 0 && array[r - 1].length > c && array[r - 1][c] == oldValue)
                queue.add(new Point(c, r - 1));
            if(r < array.length - 1 && array[r + 1].length > c && array[r + 1][c] == oldValue)
                queue.add(new Point(c, r + 1));
            if(c > 0 && array[r][c - 1] == oldValue)
                queue.add(new Point(c - 1, r));
            if(c < array[r].length - 1 && array[r][c + 1] == oldValue)
                queue.add(new Point(c + 1, r));
        }
    }

    /*
     * Walks around the edges of the array and floods everthing connected to
     * them with ones. This relies on floodFill exiting early for areas that
     * were already filled.
     */
    private static void fillEdges(int[][] array)
    {
        // top row
        for(int col = 0; col < array[0].length; col++)
            floodFill(array, 0, col, 1);
        // left column
        for(int row = 0; row < array.length; row++)
            floodFill(array, row, 0, 1);
        // bottom row
        for(int col = 0; col < array[array.length - 1].length; col++)
            floodFill(array, array.length - 1, col, 1);
        // all trailing row segments (allows for ragged arrays)
        for(int row = 1; row < array.length - 1; row++) {
            int lengthToFill = array[row].length - Math.min(array[row - 1].length, array[row + 1].length);
            lengthToFill = (lengthToFill < 0) ? 1 : lengthToFill + 1;
            for(int col = array[row].length - lengthToFill; col < array[row].length; col++)
                floodFill(array, row, col, 1);
        }
    }

    public static void main(String[] args)
    {
        fillEdges(a);
        for(int row = 0; row < a.length; row++) {
            for(int col = 0; col < a[row].length; col++) {
                if(a[row][col] == 0)
                    System.out.println("[" + row + "][" + col + "]");
            }
        }
    }
}

这个特殊的实现很好,因为它适用于任意大小和形状的数组。我添加了一点来检查一个点是否在一个参差不齐的数组的边缘(比较行的长度)。

输出正是您所期望的:

[2][3]
[3][1]
[3][2]
[3][3]
[3][4]
[4][2]
[4][4]

答案 1 :(得分:-1)

这是一个简单的算法,它使用辅助函数来计算每个元素的前导和后继的索引。

public class Test {

    public static final int N = 6;

    public static int isucc(int i, int j) {
        return (i * N + j + 1) / N;
    }

    public static int jsucc(int i, int j) {
        return (i * N + j + 1) % N;
    }

    public static int ipred(int i, int j) {
        return (i * N + j - 1) / N;
    }

    public static int jpred(int i, int j) {
        return (i * N + j - 1) % N;
    }



    public static void main(String[] args) {

        int[][] a={
                {0,0,0,0,0,0},
                {0,0,0,1,0,0},
                {0,1,1,0,1,0},
                {1,0,0,0,0,1},
                {0,1,0,1,0,1},
                {0,0,1,0,1,0}
            };



        for (int i = 0; i < N; i++) {
            for (int j = 0; j < N; j++) {        
                if (i * N + j > 0 && i * N + j < N * N - 1 
                            && a[ipred(i,j)][jpred(i,j)] == 1 
                            && a[isucc(i,j)][jsucc(i,j)] == 1) {
                    System.out.println(i +  "," + j);
                }
            }
        }


    }

}

打印:

2,3
2,5
4,0
4,2
4,4
5,3

请注意,它可以很容易地扩展到非方形矩阵。

Dominique Ubersfeld