计算矩阵中的零个岛

时间:2015-01-02 03:15:26

标签: java recursion

我正在尝试按照众所周知的计数岛问题进行编程。

并没有给我预期的输出。我哪里错了? 我的假设是,如果0触摸第0行或列或矩阵的维度...它将不会被视为岛屿

这是我的代码

public class Matrix {
    static int rowCount = 5;
    static int columnCount = 4;
    static int[][] matrix = {   {1,1,1,1,1},
                                {1,0,0,0,1},
                                {1,1,1,1,1},
                                {1,1,1,0,1}
                     };
    static boolean[][] visited = new boolean[rowCount][columnCount];    
    private static int countIslands = 0;    
    public static void main(String[] args) {
        try{
            for(int i=0; i<rowCount; i++){
                for(int j=0; j<columnCount; j++){
                    if(matrix[i][j]==0){                        
                        checkZeros(matrix, i, j);
                        System.out.println("returned " + i + j);
                    }
                }
            }
            System.out.println(visited);
        }catch(Exception e){
        }
        System.out.println(countIslands);
    }
    private static void checkZeros(int[][] matrix2, int i, int j) {
        boolean valueWithinLimits = withinLimits(i,j);      
        System.out.println("checking for " + i + j);
        if(valueWithinLimits) && checkAlreadyVisited(i,j)){
            if(matrix[i][j+1]==0){ 
                checkZeros(matrix2, i, j+1);   
            }
            if(matrix[i+1][j+1]==0){ 
                checkZeros(matrix2, i+1, j+1);
            }
            if(matrix[i+1][j]==0){
                checkZeros(matrix2, i+1, j);   
            } 
            if(matrix[i+1][j-1]==0){
                checkZeros(matrix2, i-1, j-1);   
            }           
            visited[i][j] = true;
            System.out.println("i reached here when ij are : " + i + j);
            countIslands ++;
        }
    }
    private static boolean checkAlreadyVisited(int i, int j) {
        System.out.println("visited found for " + i + j);
        return visited[i][j-1] || visited[i-1][j-1] || visited[i-1][j] || visited[i-1][j+1];
    }
    private static boolean withinLimits(int i, int j) {
        return (i>0 && i<rowCount-1 && j>0 && j<columnCount-1);
    }
}

3 个答案:

答案 0 :(得分:3)

以下解决方案经过测试,可以完全正常使用

package com.divyanshu.island;

/**
 * <b>Assumption 1 : 1 is Land, 0 is water.</b>
 * <b>Assumption 2 : It is all water outside the matrix.</b>
 * 
 * Instantiate IslandCounter by passing a m*n matrix.
 * Method getIslandCount gives you the count of island formed.
 * 
 * </br></br>Or</br></br>
 * 
 * Method getIslandCount gives the count of all connected 1s in a m*n matrix with values in 1 or 0.
 */
public class IslandCounter {

    private Integer[][] matrix;

    public IslandCounter(Integer[][] matrix) {
        this.matrix = matrix;
    }

    public int getIslandCount() {
        int count = 0;
        if (matrix == null || matrix.length == 0) {
            return count;
        }
        Integer[][] tempMatrix = matrix.clone();
        for (int i = 0; i < tempMatrix.length; i++) {
            for (int j = 0; j < tempMatrix[i].length; j++) {
                if (detectIsland(tempMatrix, false, i, j, matrix.length - 1, matrix[i].length - 1)) {
                    count++;
                }
            }
        }
        return count;
    }

    private boolean detectIsland(Integer[][] tempMatrix,
                                 boolean islandDetected,
                                 int i,
                                 int j,
                                 int iMax,
                                 int jMax) {
        if (i > iMax || j > jMax || i < 0 || j < 0 || tempMatrix[i][j] == 0) {
            return islandDetected;
        } else {
            tempMatrix[i][j] = 0;
            islandDetected = true;
            detectIsland(tempMatrix, islandDetected, i - 1, j, iMax, jMax);
            detectIsland(tempMatrix, islandDetected, i, j - 1, iMax, jMax);
            detectIsland(tempMatrix, islandDetected, i + 1, j, iMax, jMax);
            detectIsland(tempMatrix, islandDetected, i, j + 1, iMax, jMax);
        }
        return islandDetected;
    }

}


===================================================================================

/**
 * 
 */
package com.divyanshu.island;

import java.util.Random;

/**
 *This is a Main-Class to test the IslandCounter.
 */
public class IslandTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Integer[][] matrix = generateMatrix();
        printMatrix(matrix);
        IslandCounter counter = new IslandCounter(matrix);
        System.out.println("Total islands in the matrix : " + counter.getIslandCount());

    }

    private static Integer[][] generateMatrix() {
        Integer[][] matrix = new Integer[4][4];
        Random random = new Random();
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                matrix[i][j] = random.nextInt(2);
            }
        }
        return matrix;
    }

    private static void printMatrix(Integer[][] matrix) {
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j] + " ");
            }
            System.out.println();
        }
    }

}

答案 1 :(得分:0)

您可以做的是添加一个排除数组:一个零的元素数组。例如,如果您在限制范围内找到零,则可以开始四处查看是否存在任何零。继续寻找,直到找到所有这些。然后将这些零中的每一个添加到排除数组中,当您继续循环时,请确保它跳过排除数组中的元素。这不是代码,而是程序逻辑的概述。

答案 2 :(得分:0)

我认为您的代码存在多个问题。

您的visited矩阵充满了假,这意味着checkAlreadyVisited将始终返回false。此外,我不明白为什么这个方法检查周围环境,看看是否访问了当前位置。使用像访问过的临时矩阵是一个好主意,但你应该打印两张地图以确保它有效。

由于之前的错误,

countIslands永远不会递增,但是一旦你解决了它,它就会在每次调用时递增(它应该匹配地图上的0的数量)。如果您希望他的解决方案使用边界约束,您必须在for循环之前在每个边框上应用他的detectIsland

Divyanshu的解决方案有效,除了它计算1并且不认为触及边界的岛屿不是岛屿(如你所说)。

要更正您的解决方案,visited矩阵在使用前必须是matrix的副本,checkAlreadyVisited应该只扫描[i][j]而不是其中的内容,而您每次通话时都不应增加countIslands

再次,在每个回合打印您的地图,并使用更简单的矩阵,如:

static int[][] matrix = {{1,1,1},
                         {1,0,1},
                         {1,1,1},};

(没看到这个问题是三个老人......无论如何,你走了)