【问题标题】:Find Clusters in a Multidimensional Array Java在多维数组 Java 中查找簇
【发布时间】:2020-05-02 21:17:45
【问题描述】:

在给定一个 0 和 1 的多维数组的情况下,我需要找到簇的数量。簇由在上、下、左或右方向非对角线相邻的 1 定义。表示以下多维数组有一个簇:

01000
01000

下一个有两个:

00100
00010

我已经编写了代码(请参阅下面的“我的代码”),但是在使用几个用例进行编译和测试时,它未能提供一致的准确答案:

当运行以下命令时,它应该产生以下结果:

运行:

package org.example;

public class App 
{
    public static void main( String[] args )
    {
        FindCluster findCluster = new FindCluster();
        FindCluster findCluster0 = new FindCluster();
        FindCluster findCluster1 = new FindCluster();
        FindCluster findCluster2 = new FindCluster();
        // Attempt 1

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

        int numOfClusters = findCluster.findNumberOfClusters(5, 5, myArr);
        System.out.println("The number of clusters found in your Array is: " + numOfClusters);

        // Attempt 2

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

        int numOfClusters0 = findCluster0.findNumberOfClusters(5, 5, myArr0);
        System.out.println("The number of clusters found in your Array is: " + numOfClusters0);

        // Attempt 3

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

        int numOfClusters1 = findCluster1.findNumberOfClusters(5, 5, myArr1);
        System.out.println("The number of clusters found in your Array is: " + numOfClusters1);

        // Attempt 4

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

        int numOfClusters2 = findCluster2.findNumberOfClusters(5, 5, myArr2);
        System.out.println("The number of clusters found in your Array is: " + numOfClusters2);
    }
}

预期结果:

The number of clusters found in your Array is: 5
The number of clusters found in your Array is: 7
The number of clusters found in your Array is: 4
The number of clusters found in your Array is: 3

实际结果:

The number of clusters found in your Array is: 5
The number of clusters found in your Array is: 6
The number of clusters found in your Array is: 3
The number of clusters found in your Array is: 4

我的代码:

package org.example;

public class FindCluster {

    private int clusters = 0;

    private boolean gridCheckArr[][] = null;

    private int gridClusterArr[][] = null;

    public void setGridCheckArr(int rows, int columns) {
        this.gridCheckArr = new boolean[rows][columns];
    }

    public void setGridClusterArr(int gridClusterArr[][]) { this.gridClusterArr = gridClusterArr; }

    public void setGridCheckInitialValues(){
        for(int r = 0;r < gridCheckArr.length; r++){
            for(int c = 0; c < gridCheckArr[r].length; c++){
                gridCheckArr[r][c] = false;
            }
        }
    }

    public Integer findNumberOfClusters(int rows, int columns, int grid[][]) {

        // Using a method to set a grid to check if location has been visited
        setGridCheckArr(rows, columns);
        // Using a method to set the initial values to false for the grid being checked
        setGridCheckInitialValues();
        // Using a method to set the the classes grid to the grid passed to the method called
        setGridClusterArr(grid);
        // Using a method that performs the checks and computation of the clusters
        gridCheck();

        return this.clusters;
    }

    public void gridCheck() {
        for(int r = 0; r < gridCheckArr.length; r++) {
            for(int c = 0; c < gridCheckArr[r].length; c++) {
                if(r == 0 && c == 0){
                    checkFirstRowBeginning(r, c);
                } else if (r == 0 && c == gridCheckArr[r].length - 1) {
                    checkFirstRowEnd(r, c);
                } else if ( r == 0 && c > 0) {
                    checkFirstRow(r, c);
                } else if (r == gridCheckArr.length - 1 && c == 0) {
                    checkLastRowBeginning(r, c);
                } else if (r == gridCheckArr.length -1 && c == gridCheckArr[r].length -1) {
                    checkLastRowEnd(r, c);
                } else if (r == gridCheckArr.length -1 && c > 0) {
                    checkLastRow(r, c);
                } else if (r > 0 && c == 0) {
                    checkRowBeginning(r, c);
                } else if (r > 0 && c == gridCheckArr[r].length -1) {
                    checkRowEnd(r, c);
                } else if (r > 0 && c > 0) {
                    checkRow(r, c);
                } else {
                    System.out.println("Oops something went wrong trying to find a grid check!!!!");
                }
            }
        }
    }

    public void checkFirstRow(int row, int column) { // checks Left, Right, Down
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column - 1] != true && this.gridCheckArr[row][column + 1] != true && this.gridCheckArr[row + 1][column] != true) {
                    this.clusters++;
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at First Row case not able to be handled array index value is: " + arrIndexValue);
        }
    }

    public void checkFirstRowBeginning(int row, int column) { // checks Right, Down
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column + 1] != true && this.gridCheckArr[row + 1][column] != true) {
                    this.clusters++;
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at First Row Beginning case not able to be handled array index value is: " + arrIndexValue);
        }
    }

    public void checkFirstRowEnd(int row, int column) { // checks Left, Down
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column - 1] != true && this.gridCheckArr[row + 1][column] != true) {
                    this.clusters++;
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at First Row End case not able to be handled array index value is: " + arrIndexValue);
        }
    }

    public void checkRow(int row, int column) { // checks Left, Right, Up, Down
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column - 1] != true && this.gridCheckArr[row][column + 1] != true && this.gridCheckArr[row - 1][column] != true && this.gridCheckArr[row + 1][column] != true) {
                    if((this.gridCheckArr[row - 1][column - 1] != true && this.gridClusterArr[row][column - 1] != 1) && (this.gridCheckArr[row - 1][column + 1] != true && this.gridClusterArr[row][column + 1] != 1) && (this.gridCheckArr[row + 1][column - 1] != true && this.gridClusterArr[row][column - 1] != 1) && (this.gridCheckArr[row + 1][column + 1] != true && this.gridClusterArr[row][column + 1] != 1)) {
                        this.clusters++;
                    }
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at a Row case not able to be handled array index value is: " + arrIndexValue);
        }
    }

    public void checkRowBeginning(int row, int column) { // checks Right, Up, Down
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column + 1] != true && this.gridCheckArr[row - 1][column] != true && this.gridCheckArr[row + 1][column] != true) {
                    this.clusters++;
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at a Row Beginning case not able to be handled array index value is: " + arrIndexValue);
        }
    }

    public void checkRowEnd(int row, int column) { // checks Left, Up, Down
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column - 1] != true && this.gridCheckArr[row - 1][column] != true && this.gridCheckArr[row + 1][column] != true) {
                    this.clusters++;
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at a Row End case not able to be handled array index value is: " + arrIndexValue);
        }
    }

    public void checkLastRow(int row, int column) { // checks Left, Right, Up
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column - 1] != true && this.gridCheckArr[row][column + 1] != true && this.gridCheckArr[row - 1][column] != true) {
                    this.clusters++;
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at Last Row case not able to be handled array index value is: " + arrIndexValue);
        }
    }

    public void checkLastRowBeginning(int row, int column) { // checks Right, Up
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column + 1] != true && this.gridCheckArr[row - 1][column] != true) {
                    this.clusters++;
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at Last Row Beginning case not able to be handled array index value is: " + arrIndexValue);
        }
    }

    public void checkLastRowEnd(int row, int column) { // checks  Left, Up
        int arrIndexValue = this.gridClusterArr[row][column];
        switch(arrIndexValue) {
            case 0:
                break;
            case 1:
                this.gridCheckArr[row][column] = true;
                if(this.gridCheckArr[row][column - 1] != true && this.gridCheckArr[row - 1][column] != true) {
                    this.clusters++;
                }
                break;
            default:
                System.out.println("Oops something went wrong when trying to check grid at Last Row End case not able to be handled array index value is: " + arrIndexValue);
        }

    }
}

当我在某些情况下手动跟踪它时,我明白为什么它会失败。但是,我一直在寻找一种可以解决该问题的算法。例如,在 myArr2 的尝试 4 中

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

在第一列标识的第一个 1 上(索引 [0][ 0])。然后,当它到达第一列([0][3] 的索引)上标识的第三个 1 时,我的逻辑检查再次将集群计数增加 1。这是不正确的,因为它实际上在集群中连接到之前在第一行中标识的前两个 1(索引 [0][0] 和 [0][1]),如果您遵循整个二维数组中相邻的1。如何创建一个逻辑算法来实现这一点?

谁能改进我的代码以修复错误或提供更好/更有效的解决方案并解释它如何/为什么更好地工作?

【问题讨论】:

    标签: java arrays algorithm sorting multidimensional-array


    【解决方案1】:
    • 要找到簇的数量,您必须在所有 4 个方向上递归移动,每当找到值为 1 的单元格时采用 depth first search 方法。

    • DFS 的工作方式是一次性标记所有连接 4 个方向的单元。所以,我们得到了一个集群。我们在搜索其他集群时不会访问同一个单元格,因为我们将这些单元格标记为已访问。

    • 为了将单元格标记为已访问,我们将其值修改为 -1,然后将其恢复为 1,以提高空间效率。

    片段:

    public class Main{
        public static void main(String[] args) {
            int myArr[][] = {
                    {1, 1, 0, 0, 1},
                    {0, 1, 0, 0, 1},
                    {1, 0, 0, 1, 1},
                    {0, 0, 0, 0, 0},
                    {1, 0, 1, 1, 0}
            };
    
    
            System.out.println(findNumClusters(myArr));
        }
    
        private static int findNumClusters(int[][] arr){
            int num_clusters = 0;
    
            for(int i=0;i<arr.length;++i){
                for(int j=0;j<arr.length;++j){
                    if(arr[i][j] == 1){
                        dfs(arr,i,j,arr.length,arr[0].length);
                        num_clusters++;
                    }
                }
            }
    
            // restore all ones
            for(int i=0;i<arr.length;++i){
                for(int j=0;j<arr.length;++j){
                    if(arr[i][j] == -1) arr[i][j] = 1;
                }
            }
    
            return num_clusters;
        }
    
        private static void dfs(int[][] arr,int x,int y,int rows,int cols){
            if(x < 0 || x == rows || y < 0 || y == cols || arr[x][y] != 1) return;
            arr[x][y] = -1; // marking a cell as visited(will be restored later)
            dfs(arr,x-1,y,rows,cols);
            dfs(arr,x+1,y,rows,cols);
            dfs(arr,x,y-1,rows,cols);
            dfs(arr,x,y+1,rows,cols);
        }
    }
    

    演示: https://www.onlinegdb.com/HJLJR56eU

    【讨论】:

    • 感谢@vivek_23 的贡献,这是惊人的创新,似乎经受住了考验。当我跟踪它时,逻辑看起来很有意义。如果我错了,请纠正我,但看起来你实际上遵循了所有可能的连接路径并将它们标记为 -1,这样任何索引都不会在检查数组每个索引的 for 循环中再次被重新访问?
    • 就我的理解而言,这意味着如果第一次找到 1 并调用它时 dfs 方法中的 if 语句的条件不满足。然后它将执行方法中的每一行附加代码,导致它递归地调用自己,直到找不到 1。此外,每次dfs方法中的一行代码再次调用该方法时,它都会返回到调用dfs方法的那一行,这是否正确?
    • 例如,dfs(arr,x-1,y,rows,cols) 调用 dfs 方法,如果满足条件语句则返回并执行 dfs(arr,x+1, y,rows,cols) 等。或者每次增加索引时它都会再次开始执行 dfs(arr,x-1,y,rows,cols) 的过程,从而导致新的位置检查,直到特定集群的所有连接的 1 都是改为-1。那准确吗?对不起,我的用户名暗示了多个 cmets/问题,我不只是想得到答案,我想在这个过程中扩大我的理解。谢谢!
    • @alwaySearchingForSolutions dfs(arr,x-1,y,rows,cols) 调用 dfs 方法,如果满足条件语句,该方法将返回并执行 dfs(arr,x+ 1,y,rows,cols) 等 这是正确的。如果不满足if 条件,那么它将递归地去新的位置。你得到的一切都绝对正确。我很高兴我的代码可读。干杯:)
    猜你喜欢
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-01
    • 2021-05-17
    • 2012-01-29
    相关资源
    最近更新 更多