【问题标题】:Use a depth first to traverse a matrix先用深度遍历矩阵
【发布时间】:2019-08-27 21:58:44
【问题描述】:

问题

给定一个二维数组(矩阵),其高度和宽度可能不相等,仅包含 0 和 1。每个 0 代表土地,每个 1 代表河流的一部分。一条河流由任意数量的 1 组成,这些 1 水平或垂直相邻(但不是对角相邻)。形成一条河流的相邻 1 的数量决定了它的大小。编写一个函数,返回一个数组,该数组包含输入矩阵中表示的所有河流的大小。请注意,这些尺寸不需要按任何特定顺序排列。

Input 
[
[1,0,0,1,0],
[1,0,1,0,0],
[0,0,1,0,1],
[1,0,1,0,1],
[1,0,1,1,0],
]

Output [1,2,2,2,5]

我的方法

在评估了问题后,我觉得这应该使用图遍历之类的算法来完成,可能是深度优先搜索。所以这正是我所做的。

我从左上角遍历矩阵,看看值是否被访问,如果不是,如果值为 1,那么我遍历它的所有节点并保留一个计数器以保持河流的大小。最后,我用河流的总大小更新了一个数组列表。

由于某种原因,我的结果不正确,我不确定我做错了什么。我也手动跟踪了我的代码,但无法找出问题所在。

我的代码

import java.util.ArrayList;

class Program {
  public static ArrayList<Integer> riverSizes(int[][] matrix) {
    ArrayList<Integer> result = new ArrayList<Integer>();
        boolean [][] visitStatus = new boolean [matrix.length][matrix[0].length];

        for(int row = 0; row<matrix.length; row++){
            for(int col = 0; col<matrix.length; col++){
                int count = 0;
                count = traverseMatrix(row,col,matrix,visitStatus,count);
                result.add(count);
            }
        }
        return result;
  }

    public static int traverseMatrix(int row, int col, int [][] matrix, boolean [][] visitStatus, int count){
        if(visitStatus[row][col] == true){
            return count;
        }else if(matrix[row][col] == 0){
            visitStatus[row][col] = true;
            return count;
        }else{
            count++;
            visitStatus[row][col] = true;
            if(isValid(row,col-1,matrix)){
                return traverseMatrix(row,col-1,matrix,visitStatus,count);
            }
            if(isValid(row,col+1,matrix)){
                return traverseMatrix(row,col+1,matrix,visitStatus,count);
            }
            if(isValid(row-1,col,matrix)){
                return traverseMatrix(row-1,col,matrix,visitStatus,count);
            }
            if(isValid(row+1,col,matrix)){
                return traverseMatrix(row+1,col,matrix,visitStatus,count);
            }
        }
        return count;
    }

    public static boolean isValid(int row, int col,int[][] matrix){
        return (row >= 0 && row < matrix.length) && (col >= 0 && col < matrix[0].length);
    }
}

【问题讨论】:

  • 在调试中运行你的测试,你会看到你的循环很快就无法检查整个数组

标签: java algorithm data-structures depth-first-search


【解决方案1】:

您将获得一个高度和宽度可能不相等的二维数组(矩阵)

但是您正在为高度和宽度始终相同大小的矩阵进行操作

for(int row = 0; row<matrix.length; row++){ 
    for(int col = 0; col<matrix.length; col++){ .. }}

你应该像下面这样使用维度,其余的东西我猜就足够了 ..

  for(int row = 0; row<matrix.length; row++){ 
    for(int col = 0; col<matrix[row].length; col++){ .. }}

并且更改也需要在函数“isValid”中应用

public static boolean isValid(int row, int col,int[][] matrix){
    return (row >= 0 && row < matrix.length) && (col >= 0 && col < matrix[row].length);
}

【讨论】:

  • isValid 中存在相同的问题。必须是&amp;&amp; col &lt; matrix[row].length
  • 是的!非常正确!
【解决方案2】:

count转换为局部变量并累加:

static int traverseMatrix(int row, int col, int[][] matrix, boolean[][] visitStatus) {
    if (visitStatus[row][col] || matrix[row][col] == 0) {
        return 0;
    }
    visitStatus[row][col] = true;
    int count = 1;
    if (isValid(row, col - 1, matrix)) {
        count += traverseMatrix(row, col - 1, matrix, visitStatus);
    }
    ...
    return count;
}

【讨论】:

    【解决方案3】:

    除了@OleksandrPyrohov 的回答,还要在调用traverseMatrix 之前检查当前单元格是否已经被访问过:

    public static ArrayList<Integer> riverSizes(int[][] matrix) {
        ArrayList<Integer> result = new ArrayList<Integer>();
            boolean [][] visitStatus = new boolean [matrix.length][matrix[0].length];
    
            for(int row = 0; row<matrix.length; row++){
                for(int col = 0; col<matrix.length; col++){
                    if ( !visitStatus[row][col] ) {
                       int count = 0;
                       count = traverseMatrix(row,col,matrix,visitStatus,count);
                       result.add(count);
                    }
                }
            }
            return result;
      }
    

    【讨论】:

    • 我试过了,还是没有通过所有的测试用例。
    • 在考虑到您建议的更改后,我刚刚发布了代码的编辑版本
    • 我没有看到您更新的代码有问题,您确定大小的顺序无关紧要吗?
    • 我刚刚发布了我的测试用例以及我的输出和预期输出。我想即使结果为 0 我似乎也在添加,但我应该只在结果不为 0 时添加。但是即使我这样做了,也不是所有的测试用例都通过了。
    • 是的,这就解释了。
    【解决方案4】:

    我的解决方案是用 C# 编写的,但它类似于 Java:

    你可以用 ArrayList 替换 List

    代码:

            public static List<int> RiverSizes(int[,] matrix)
            {
                var sizes = new List<int>();
                bool[,] visited = new bool[matrix.GetLength(0), matrix.GetLength(1)];
    
                for (int row = 0; row < matrix.GetLength(0); row++)
                    for (int col = 0; col < matrix.GetLength(1); col++)
                        if (visited[row, col])
                            continue;
                        else
                            Traverse(matrix, row, col, visited, sizes);
               return sizes;
            }
    
            public static void Traverse(int[,] matrix, int row, int col, bool[,] visited, List<int> sizes)
            {
                int currentSize = 0;
                var toExplore = new List<int[]>
                {
                    new int[] { row, col }
                };
    
                while (toExplore.Count > 0)
                {
                    var current = toExplore[^1];
                    toExplore.RemoveAt(toExplore.Count - 1);
                    row = current[0];
                    col = current[1];
    
                    if (visited[row, col])
                        continue;
    
                    visited[row, col] = true;
    
                    if (matrix[row, col] == 0)
                        continue;
    
                    currentSize++;
    
                    foreach (int[] item in GetNeighbours(matrix, row, col, visited))
                        toExplore.Add(item);
                }
    
                if (currentSize > 0)
                    sizes.Add(currentSize);
    
            }
    
            public static List<int[]> GetNeighbours(int[,] matrix, int row, int col, bool[,] visited)
            {
                List<int[]> neighbours = new List<int[]>();
    
                if (row > 0 && !visited[row - 1, col])
                    neighbours.Add(new int[] { row - 1, col });
    
                if (row < matrix.GetLength(0) - 1 && !visited[row + 1, col])
                    neighbours.Add(new int[] { row + 1, col });
    
                if (col > 0 && !visited[row, col - 1])
                    neighbours.Add(new int[] { row, col - 1 });
    
                if (col < matrix.GetLength(1) - 1 && !visited[row, col + 1])
                    neighbours.Add(new int[] { row, col + 1 });
                return neighbours;
            }
    

    希望对你有帮助^-^

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-10
      • 2019-01-08
      • 1970-01-01
      相关资源
      最近更新 更多