【问题标题】:BFS algorithm does not mark all nodes in the Rotten Oranges problem on Leetcode [closed]BFS 算法没有标记 Leetcode 烂橙问题中的所有节点 [关闭]
【发布时间】:2020-09-25 21:34:11
【问题描述】:

我正在处理rotten oranges problem

在给定的网格中,每个单元格可以具有以下三个值之一:

  • 值 0 表示空单元格;
  • 值 1 代表新鲜的橙子;
  • 代表烂橙的值 2。

每分钟,任何与(4 向)相邻的新鲜橙子 烂橘子变烂了。

返回在没有单元格之前必须经过的最小分钟数 有一个新鲜的橙子。如果这是不可能的,则返回 -1。

示例 1:

  • 输入:[[1,1,1],[1,1,0],[0,1,2]]
  • 输出:4

我已经实施了 BFS 解决方案。然后在完成 BFS 之后,我开始另一个迭代以确保没有新鲜的橙子剩下,因为如果有新鲜的橙子剩下,那么我必须返回 -1。

但是,我发现在最后一个循环中,只有一些值更改为 2,而其他一些值保持为 1。我不确定为什么它们也没有更改为 2。

class Solution {
    public int orangesRotting(int[][] grid) {
        //need adjacency list/matrix
        Queue<String> q = new LinkedList<>();
        int[] count = new int[1];
        count[0] = 0;
        for(int i = 0; i < grid.length; i++) {
            for(int j = 0; j < grid[i].length; j++) {
                if(grid[i][j] == 2) {
                    q.add("" + i + j);
                    bfs(grid, i, j, count, q);
                }
            }
        }
        
        for(int i = 0; i < grid.length; i++) {
            for(int j = 0; j < grid[i].length; j++) {
                // does NOT always print correct value: 1 is not changed to 2
                System.out.println(grid[i][j]); 
                if(grid[i][j] == 1) {
                    return -1;  // ... and so this -1 is returned when it shouldn't
                }
            }
        }
        
        return count[0];
    }
    
    private static void bfs(int[][] grid, int i, int j, int[] count,  Queue<String> q) {
        while(!q.isEmpty()) {
            String s = q.remove();
            //System.out.println(s); //prints correct indices
            i = Integer.parseInt(s.substring(0,1));
            j = Integer.parseInt(s.substring(1));
            
            if(i - 1 > 0 && grid[i - 1][j] == 1) {
                count[0]++;
                i--;
                grid[i][j] = 2;
                q.add("" + i + j);
            }
            if(i + 1 < grid.length && grid[i + 1][j] == 1) {
                count[0]++;
                i++;
                grid[i][j] = 2;
                q.add("" + i + j);
            }
            if(j - 1 > 0 && grid[i][j - 1] == 1) {
                count[0]++;
                j--;
                grid[i][j] = 2;
                q.add("" + i + j);
            }
            if(j + 1 < grid.length && grid[i][j + 1] == 1) {
                count[0]++;
                j++;
                grid[i][j] = 2;
                q.add("" + i + j);
            }
        }
        
    }
    
}

我的代码为上面引用的示例输出 -1,因为它仍然在最终循环中找到 1,而它不应该。

你能帮我弄清楚为什么会这样吗?

【问题讨论】:

  • 否则?输入一个 if 后,可以输入第二个 if。可以介绍一个nextI
  • @JoopEggen 这应该会发生,因为橙色可能是你旁边的 4 个其他没有腐烂的橙色,并且在一次 bfs 迭代中它们都应该被添加到队列中
  • 你能解释一下什么“烂橙子问题”到底是什么吗?

标签: java algorithm graph pass-by-reference breadth-first-search


【解决方案1】:

几个问题:

  • 永远不会检查第 0 列或第 0 行中的单元格是否感染橙子。当i 为1 时,比较i - 1 &gt; 0 不正确,但您还应该检查grid[0][j]...j 也会出现同样的问题。

  • 通过用i-- 修改i,您会影响下一个if 条件,这些条件旨在查看i 的原始值。所以你不应该改变i的值(也不是j),而是分配给grid[i-1][j]而不修改i

  • bfs 中,j 索引与grid.length 的比较错误。它应该与grid[i].length 进行比较,因为不能保证网格是正方形的。

  • 每个腐烂的橙子的计数都会增加,但这不是应该计算的。许多橙子会在同一分钟内腐烂,你应该只计算分钟数,而不是橙子。要正确计数,您应该进行两项更改:

    • 只有在您收集完队列中的所有烂橘子后才首次调用bfs,因为它们都属于第0分钟。

    • bfs 函数本身中,将新的烂橙子添加到单独的队列中,这样您就知道在这一特定分钟内添加了哪些烂橙子。然后当原始队列变空时,将第二个队列移动到第一个队列,等待下一分钟,然后重复。

  • 没问题,但是不需要将ij 作为参数传递给bfs,而不是传递对计数器的引用,让bfs 返回计数。

我已尝试在您的代码中不进行超出必要的更改以使其正常工作:

class Solution {
    public int orangesRotting(int[][] grid) {
        Queue<String> q = new LinkedList<>();
        for(int i = 0; i < grid.length; i++) {
            for(int j = 0; j < grid[i].length; j++) {
                if(grid[i][j] == 2) {
                    q.add("" + i + j);
                }
            }
        }
        // Only call BFS when all rotten oranges on "minute 0" are identified
        int count = bfs(grid, q);       
        for(int i = 0; i < grid.length; i++) {
            for(int j = 0; j < grid[i].length; j++) {
                System.out.println(grid[i][j]); //does NOT print correct value, not changed to 2
                if(grid[i][j] == 1) {
                   return -1;
                }
            }
        }      
        return count;
    }
    
    private static int bfs(int[][] grid, Queue<String> q) {
        int count = 0;
        while(true) { // One iteration per minute
            // Use another queue for the next minute
            Queue<String> q2 = new LinkedList<>();
            // Populate the new queue with oranges that get rotten in this minute
            while(!q.isEmpty()) {
                String s = q.remove();
                int i = Integer.parseInt(s.substring(0,1));
                int j = Integer.parseInt(s.substring(1));
                if(i - 1 >= 0 && grid[i - 1][j] == 1) {
                    // Do not increase the counter for each separate orange!
                    // ...and do not change the value of i or j.
                    grid[i-1][j] = 2;
                    q2.add("" + (i-1) + j);
                }
                if(i + 1 < grid.length && grid[i + 1][j] == 1) {
                    grid[i+1][j] = 2;
                    q2.add("" + (i+1) + j);
                }
                if(j - 1 >= 0 && grid[i][j - 1] == 1) {
                    grid[i][j-1] = 2;
                    q2.add("" + i + (j-1));
                }
                // Compare against the correct length
                if(j + 1 < grid[i].length && grid[i][j + 1] == 1) {
                    grid[i][j+1] = 2;
                    q2.add("" + i + (j+1));
                }
            }
            if (q2.isEmpty()) { // No new oranges were turned rotten
                return count;
            }
            // Continue for a next minute: only now increase the counter
            count++;
            q = q2;
        }
    } 
}

肯定有一些方法可以提高运行效率,比如使用数组而不是队列。

【讨论】:

  • 谢谢!!你的解释澄清了很多事情。
猜你喜欢
  • 2021-11-25
  • 2020-11-01
  • 2022-06-12
  • 2014-01-20
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
相关资源
最近更新 更多