【问题标题】:Finding the number of nodes at each level during bfs在 bfs 期间查找每个级别的节点数
【发布时间】:2016-10-13 12:45:26
【问题描述】:

给你一棵由 N 个节点组成的树。树是由 N 个节点和 N-1 条边组成的全连接图。这棵树中的节点的索引从 1 到 N。将索引为 1 的节点视为这棵树的根节点。根节点位于树中的第一层。您将获得树和一个整数 x 。您需要找出位于 x 层上的节点数。

输入格式

第一行由一个整数 N 组成,表示树中的节点数。接下来的 n-1 行中的每一行都由 2 个整数 a 和 b 组成,表示节点 a 和节点 b 之间的无向边。下一行包含一个整数 x。

输出格式

您需要打印一个整数来表示 x 层上的节点数。


下面是我写的sn-p代码,它不正确。请帮我找出错误。

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Scanner;

public class LevelNodes {
    public static ArrayList[] adj;
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N = sc.nextInt();
        boolean[] visites = new boolean[N];
        ArrayList[] adj = new ArrayList[N];
        for(int j=0;j<N;j++){
            adj[j] = new ArrayList();
        }
        for(int i = 0;i < (N-1) ;i++){
            int a = sc.nextInt();
            int b = sc.nextInt();
            adj[a-1].add(b);
            adj[b-1].add(a);
        }
        int level = sc.nextInt();
        int counter = 0;
        LinkedList list = new LinkedList();
        list.add(1);
        counter++;
        while(!list.isEmpty()){
            int n = (Integer) list.poll();
            for(int x = 0; x< adj[n-1].size();x++){
                list.add(adj[n-1].get(x));
            }
            counter++;
            if(counter == level){
                System.out.println(list.size());
                break;
            }

        }
    }

}

【问题讨论】:

  • 嗨@Vivek,欢迎来到SO!您是否尝试过调试您的代码?你认为问题出在哪里?您当前的行为是什么,为什么不正确?
  • 你得到什么错误信息?
  • counter 永远不等于level 时,您可能想要添加if (level &lt;= 0 || N &lt;= level) { System.out.println("0"); System.exit(0); } 和类似内容。
  • 只是一个友好的提示,您可能需要阅读此页面:How-To-Ask Guide,这样您就可以始终确保您的问题易于回答且尽可能清晰。请务必包括您为解决遇到的问题所做的任何努力,以及尝试这些修复时发生的情况。也不要忘记您的显示代码和任何错误消息!

标签: java algorithm graph tree breadth-first-search


【解决方案1】:

你的代码有很多问题:

第一个问题是您的代码可能不会终止。这是因为您将两个边 u->v 和 v->u 添加到邻接列表中。因此,每当您从列表中轮询 u 并添加其邻居时,您都会将 v 添加到列表中。同样,每当您轮询 v 并添加其邻居时,您都会将 u 添加回列表中。您需要维护一个布尔数组 visited 并在将 u 添加到列表时设置 visited[u]=true 。这样您就可以只将未访问的节点添加到您的扫描列表中。

另一个主要问题是在while循环中。每当您访问新节点时,您都​​会增加级别计数器变量counter++;。考虑下面的树并假设我们需要找到第 2 层(最后一层)的节点数。

     1
    / \
   2   3
  / \ / \
 4  5 6  7

您的列表最初包含 1 和 counter=1。在第一次迭代中,您从列表中轮询 1 并添加其邻居:2 和 3。在此阶段,counter=2。在接下来的两次迭代中,您将从列表中删除 2 然后 3,添加它们的邻居,并每次增加 counter。因此,当您到达第二级时,counter 将等于 4。If 语句将永远不会被执行。

要解决此问题,您必须增加counter,前提是您已处理完当前级别的所有节点。一种简单(未经测试)的方法是使用第二个临时列表来保存当前级别的所有节点的邻居。然后,每当原始列表为空时,您就知道您已经处理了当前级别的所有节点。在这里,您增加 counter 并将所有节点从临时列表移动到主列表。

while(!list.isEmpty()){
    int n = (Integer) list.poll();
    for(int x = 0; x< adj[n-1].size();x++){
        tmpList.add(adj[n-1].get(x));
    }

    if(list.isEmpty()) {
        if(counter == level){
            System.out.println(tmpList.size());
            break;
        }

        list.addAll(tmpList);
        tmpList.clear();
        counter++;
    }
}

【讨论】:

  • (我可能会使用currentnext 而不是listtmpList,以及current = next; next = new ListImpl(); 以进入下一个级别。并练习使用Streams,如果不是“foreach-loops”而不是polling。最肯定的是,我会从(doc)cmets开始。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多