如何避免BFS中的无限循环?

时间:2019-01-07 14:19:14

标签: java algorithm breadth-first-search

这是LeetCode问题542. 01 Matrix

我的代码将创建一个无限循环,因为它将把每个方向推入队列,即使该节点已经被访问过也是如此。 我想不出解决这个问题的方法。有人可以帮忙吗?

// Handle incoming messages
messaging.onMessage(function(payload) {
  console.log("Notification received: ", payload);
  toastr["success"](payload.notification.body, payload.notification.title, {
      "closeButton": true,
      "debug": false,
      "newestOnTop": false,
      "progressBar": true,
      "positionClass": "toast-top-left",
      "onclick": payload.notification.click_action, // I also tried removing this
      "preventDuplicates": false,
      "showDuration": 30000,
      "hideDuration": 1000,
      "timeOut": 0,
      "extendedTimeOut": 0,
      "showEasing": "swing",
      "hideEasing": "linear",
      "showMethod": "fadeIn",
      "hideMethod": "fadeOut"
       });  
});

2 个答案:

答案 0 :(得分:3)

您必须跟踪已访问的节点。您可以将节点保留在列表中,也可以将它们移动到单独的Set

这里的问题是节点是数组,不能在HashSet中使用它们。我将首先声明一个类Coordinates

public class Coordinates {
    public final int row;
    public final int col;

    public Coordinates(int r, int c) {
        this.row = r;
        this.col = c;
    }

    @Override
    public int hashCode() {
        return (row + 37*col) & 0x7FFFFFFF;
    }

    @Override
    public boolean equals(Object other) {
        if (other == null || other.getClass() != getClass()) {
            return false;
        }
        Coordinates o = (Coordinates)other;
        return row == o.row && col == o.col;
    }
}

选项1:将节点保留在队列中

我不明白将null添加到队列中的目的;我刚刚删除了这个。

public void BFS(Coordinates node,int[][] matrix){
    if(matrix[node.row][node.col] == 0)
        return;
    List<Coordinates> queue = new ArrayList<>();
    queue.add(node);
    for (int i = 0; i < queue.size(); ++i) {
        Coordinates temp = queue.get(i);
        for(int[] dir:dirs){
            int r = temp.row + dir.row;
            int c = temp.col + dir.col;
            if(r < 0 || c < 0 || r >= matrix.length || c >= matrix[r].length)
                continue;
            Coordinates newCoord = new Coordinates(r, c);
            if (!queue.contains(newCoord)) {
                queue.add(newCoord);
            }
            if(matrix[r][c] == 0){
                matrix[temp.row][temp.col] = Math.min(step,matrix[temp.row][temp.col]);
            }
        }
    }
    return;
}

选项2:使用单独的Set

现在我们有一个hashCode和一个equals方法,为什么不使用HashSet

不过,我将保留此练习。

答案 1 :(得分:0)

按照this答案中的建议,将节点地址封装在可以实现哈希码和等于值的类中。节点类可以很简单:

class Node {

    private final int[] address;
    Node(int[] address){
        this.address = address;
    }

    @Override
    public boolean equals(Object other) {
        if(other == null ||!(other instanceof Node)) return false;
        return Arrays.equals(address, ((Node)other).getAddress());
    }

    @Override
    public int hashCode() {
        return Arrays.hashCode(address);
    }

    public int[] getAddress() {
        return address;
    }
}

它允许您维护访问的节点的集合:Set<Node> visited = new HashSet<>();
visited.add(node)返回false时,您知道visited已经包含node