簡體   English   中英

按元素位置在二維數組中查找鄰居

[英]find neighbours in 2d array by position of elements

我需要通過元素的位置在二維數組中找到鄰居

可用數據:

網格的大小 例如 - 3*3 將返回 3,4*4 將返回 4

網格中填充單元格的數量 例如 - 4

獲取填充單元格的 x 坐標- 例如 0 或 1 或 2 等

獲取填充單元格的 y 坐標- 例如 0 或 1 或 2 等

例如

int[][] room = {
            {0, 0, X},
            {0, X, 0},
            {X, 0, 0}
    };

這里,網格的大小 = 3

網格中填充單元格的數量 = 3(因為有三個“X”,它在其他單元格上的值無關緊要)

獲取填充單元格的 x 坐標 - 第一個元素為 0,第二個元素為 1,第三個元素為 2

獲取填充單元格的 y 坐標 - 第一個元素為 2,第二個元素為 1,第三個元素為 0

所以,坐標變成 (0,2),(1,1),(2,0)

我需要用至少一個相鄰的“X”來計算“X”的數量。 如果“X”在基本方向上彼此相鄰,但不是對角線,則它們被認為是鄰居。 所以上面的情況將返回0。

int[][] room = {
            {X, X, 0},
            {0, 0, 0},
            {0, 0, 0}
    };

這應該返回 2。

我使用的語言是 Java。

我嘗試迭代填充元素的數量並使用如下所示的鄰居邏輯,但在某些或其他情況下它會中斷你上面的鄰居 = (x, y-1),

你下面的鄰居 = (x, y+1),

你左邊的鄰居 = (x-1, y),

你右邊的鄰居 = (x+1, y)

for (int x = 0; x < nums; x++) {
        int xcord = xmap.get(x); //return x cord
        int ycord = ymap.get(x); //return y cord
        int xcordLeft = x - 1 >= 0 ? xmap.get(x - 1) : 0;
        int ycordLeft = x - 1 >= 0 ? ymap.get(x - 1) : 0;

        int xcordRight = x + 1 < size ? xmap.getOrDefault(x + 1, 0) : 0;
        int ycordRight = x + 1 < size ? ymap.getOrDefault(x + 1, 0) : 0;

        int xcordTop = xcord - 1 >= 0 ? xmap.get(xcord - 1) : 0;
        int ycordTop = ymap.get(ycord);

        int ycordBottom = ymap.get(ycord);*/
        //left
        if (xcord >= 0 && x - 1 >= 0 && xcord == xcordLeft && ycord - 1 == ycordLeft) {
            neighbours++;
        }
        //right
        if (xcord >= 0 && x + 1 < size && xcord == xcordRight && ycord + 1 == ycordRight) {
            neighbours++;
        }
        //top
        if (xcord >= 0 && xcord - 1 >= 0 && xcord - 1 == xcordTop && ycord == ycordTop) {
            neighbours++;
        }

        //bottom
    }

您正在使用指定 X 位置的坐標列表。

當曼哈頓距離為 1 時,兩個單元格p ( x p , y p ) 是q ( x q , y q ) 相鄰的:

| x px q | + | y py q | = 1

與其嘗試查找頂部、底部、左側和右側鄰居的坐標並在列表中查找它們,不如遍歷列表並計算鄰居:

for (int i = 0; i < nums; i++) {
    int x = xmap.get(i);
    int y = ymap.get(i);
    int neighbors = 0;

    for (int j = 0; j < nums; j++) {
        int xx = xmap.get(j);
        int yy = ymap.get(j);

        if ((abs(x - xx) + abs(y - yy) == 1) {
            neighbors++;
        }
    }

    if (neighbors) // do stuff
}

一個單元格到它自己的曼哈頓距離是 0,所以它不算作鄰居。 該代碼對於大而密集的網格不是很有效,但是如果您的 X 很少,那么嵌套的 lops 應該沒問題。

讓它簡單明了。
通過檢查所有四個相鄰坐標來計算鄰居,並有一些條件來檢查相鄰坐標是否在邊界內:

bool inBounds(int x, int y){
    return 0 <= x and x < size and 0 <= y and y < size;
}

int countNeighbours(int x, int y) {
    int count = 0;
    for(int i=-1; i<=1; i+=2){
        if(inBounds(x+i, y))
            if(data[x+i][y] == X){
                count++;
            }
        }
        if(inBounds(x, y+i))
            if(data[x][y+i] == X){
                count++;
            }
        }
    }
    return count;
}

int countGroupedEntries(){
    int count = 0;
    for(int x=0; x<size; x++){
        for(int y=0; y<size; y++){
            if(data[x][y] == X){
                if(countNeighbours(x,y) != 0){
                    count++;
                }
            }
        }
    }
    return count;
}

我的意思是,這里的某些算法可能更聰明,但是如果您沒有一些效率瓶頸,請使算法盡可能簡單,使其具有可讀性(並不是說該算法特別糟糕,僅適用於 Θ(size²)很好,唯一需要考慮的是線性因素)。
執行inBounds檢查而不是確保您在特殊情況下保持在邊界內可以防止countNeighbours方法過度擁擠。

如果您想計算鄰居關系的數量,您可以:

private int countNeighborRelations(int[][] array, int yourX) {
    int neighborRelationCount = 0;
    for (int y = 0; y < array.length; y++) {
        for (int x = 0; x < array[y].length - 1; x++) {
            if (array[y][x] == yourX && array[y][x + 1] == yourX) {
                neighborRelationCount += 2;
            }
        }
    }
    for (int y = 0; y < array.length - 1; y++) {
        for (int x = 0; x < array[y].length; x++) {
            if (array[y][x] == yourX && array[y + 1][x] == yourX) {
                neighborRelationCount += 2;
            }
        }
    }
    return neighborRelationCount;
}

如果您想計算您的 X 中有多少具有 neigbourHoodRelations(換句話說,所有 X 至少有一個鄰居),您可以使用以下代碼:

private int countNeighbors(int[][] array, int yourX) {
    int[][] neighborRelationCount = new int[array.length][array[0].length];
    for (int y = 0; y < array.length; y++) {
        for (int x = 0; x < array[y].length - 1; x++) {
            if (array[y][x] == yourX && array[y][x + 1] == yourX) {
                neighborRelationCount[y][x]++;
                neighborRelationCount[y][x + 1]++;
            }
        }
    }
    for (int y = 0; y < array.length - 1; y++) {
        for (int x = 0; x < array[y].length; x++) {
            if (array[y][x] == yourX && array[y + 1][x] == yourX) {
                neighborRelationCount[y][x]++;
                neighborRelationCount[y + 1][x]++;
            }
        }
    }
    int neighbourCount=0;
    for (int y = 0; y < neighborRelationCount.length; y++) {
        for (int x = 0; x < neighborRelationCount[y].length; x++) {
            if (0<neighborRelationCount[y][x]) {
                neighbourCount++;
            }
        }
    }
    return neighbourCount;
}

當然,如果您確實使用其他數據格式,則有更簡單的解決方案,但使用原始 int[][] 我認為這是最簡單的方法。

以下是我測試功能的方法:

    @Test
    public void testRelations() {
        // TODO Auto-generated method stub
        int[][] room0_0 = { { 1, 0, 1 }, { 0, 1, 0 }, { 1, 0, 1 } };
        int[][] room2_2 = { { 1, 1, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
        int[][] room4_3 = { { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 0 } };
        int[][] room4_4 = { { 1, 1, 0 }, { 0, 0, 0 }, { 0, 1, 1 } };
        int[][] room8_5 = { { 1, 1, 0 }, { 0, 1, 0 }, { 0, 1, 1 } };
        int[][] room24_9 = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };
        assertTrue(countNeighborRelations(room0_0, 1)==0);
        assertTrue(countNeighborRelations(room2_2, 1)==2);
        assertTrue(countNeighborRelations(room4_3, 1)==4);
        assertTrue(countNeighborRelations(room4_4, 1)==4);
        assertTrue(countNeighborRelations(room8_5, 1)==8);
        assertTrue(countNeighborRelations(room24_9, 1)==24);
        assertTrue(countNeighbors(room0_0, 1)==0);
        assertTrue(countNeighbors(room2_2, 1)==2);
        assertTrue(countNeighbors(room4_3, 1)==3);
        assertTrue(countNeighbors(room4_4, 1)==4);
        assertTrue(countNeighbors(room8_5, 1)==5);
        assertTrue(countNeighbors(room24_9, 1)==9);
    }

編輯為完整請求的功能添加了完整的實現

以下代碼的復雜度為 O(gridSize^2)

private int neigbours(Collection<CoordinatedObject> cos,int gridSize) {
    boolean[][] array=new boolean[gridSize][gridSize];
    for(CoordinatedObject co:cos) {
        array[co.getX()][co.getY()]&=true;
    }
    boolean[][] neighborRelations = new boolean[array.length][array[0].length];
    for (int y = 0; y < array.length; y++) {
        for (int x = 0; x < array[y].length - 1; x++) {
            if (array[y][x] && array[y][x + 1]) {
                neighborRelations[y][x]&=true;
                neighborRelations[y][x + 1]&=true;
            }
        }
    }
    for (int y = 0; y < array.length - 1; y++) {
        for (int x = 0; x < array[y].length; x++) {
            if (array[y][x] && array[y + 1][x]) {
                neighborRelations[y][x]&=true;
                neighborRelations[y + 1][x]&=true;
            }
        }
    }
    int neighbourCount=0;
    for (int y = 0; y < neighborRelations.length; y++) {
        for (int x = 0; x < neighborRelations[y].length; x++) {
            if (neighborRelations[y][x]) {
                neighbourCount++;
            }
        }
    }
    return neighbourCount;
}

我假設您將所有 x 的坐標按順序存儲在兩張地圖中(一張用於 x,一張用於 y)。 所以例如

    {X , X , 0 , X},
    {X , 0 , X , X}
    {0 , 0 , X , X}
    {X , X,  0 , 0}

所以你的地圖會有這樣的條目

    xmap = {
            0 : 0,
            1 : 1,
            2 : 3,
            3 : 0,
            4 : 2,
            5 : 3,
            6 : 2,
            7 : 3,
            8 : 0,
            9 : 1
        }
    ymap = {
            0 : 0,
            1 : 0,
            2 : 0,
            3 : 1,
            4 : 1,
            5 : 1,
            6 : 2,
            7 : 2,
            8 : 3,
            9 : 3,
        }

我認為左右可以像這樣編輯

      //left
        if (xcord >= 0 && x - 1 >= 0 && xcord - 1 == xcordLeft && ycord == ycordLeft) {
            neighbours++; //comparing (x - 1 , y) && (x , y)
        }
      //right
        if (xcord >= 0 && x + 1 < size && xcord + 1 == xcordRight && ycord == ycordRight) {
            neighbours++; // comparing(x , y) && (x + 1 , y)
        }

實際上 xcordTop 應該是 ycordTop 但讓我們假設它相當於找到頂部元素

the mistake you are doing is that how can you be sure that
int xcordTop = xcord - 1 >= 0 ? xmap.get(xcord - 1) : 0; will give you coordinate of just upper element, because key of
the map is not x coordinates it is just numbering of X'S

所以對於給定矩陣中的第 7 個 X(其索引為 6,以 0 為基礎的編號),讓我們取它的 x 和 y 坐標

xcord = 2 
ycord = 2
now let's us take xmap.get(2)
what do we get xcordTop = 0

即使我們從 ycordTop 邏輯出發,它也會給我們錯誤的坐標,因為地圖鍵值只是總 X 序列的值

so let's take ymap.get(ycord) 
ycord = 2
so ycordTop = ymap.get(2) 
we get ycordTop = 0 so which is 0th row

所以一個簡單的解決方案是遍歷二維數組並檢查你提到的所有鄰居

for(int y = 0; y < array.length; ++y){
    for(int x = 0; x < array[y].length; ++x){
        if(array[x][y] == 'X'){
            if(x - 1 >= 0 && array[x - 1][y] == 'X'){
                ++neighbors;
            }
            else if(x + 1 < array[y].length && array[x + 1][y] == 'X'){
                ++neighbors;
            }
            else if(y - 1 >= 0  && array[x][y - 1] == 'X'){
                ++neighbors;
            }
            else if(y + 1 < array.length && array[x][y + 1] == 'X'){
                ++neighbors;
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM