【问题标题】:find a smaller group of friends from the circle?从圈子里找一小群朋友?
【发布时间】:2019-01-24 23:56:20
【问题描述】:

我正在解决以下问题:

在一个有人的房间里,我们将定义两个人是朋友,如果他们 是直接或间接的朋友。如果 A 是 B 的朋友,而 B 是 是 C 的朋友,那么 A 也是 C 的朋友。一群朋友是一个 一组人,其中任何两个人都是朋友。给定 直接是朋友的人的列表,找到最小的组 朋友..

示例: 输入:

1<->6 
2<->7
3<->8
4<->9
2<->6
3<->5

组:

1-6-2-7
3-8-5
4-9

最小组的人数是 2,即 4-9,所以我们应该返回 2。

我想出了下面的代码,但我现在不明白如何使用这个holder 映射来获得所需的输出。我在这里有点困惑。解决此问题的最佳方法是什么?

  private static int findGroups(final List<List<Integer>> inputs) {
    if (inputs == null || inputs.isEmpty()) {
      return 0;
    }
    int count = Integer.MAX_VALUE;

    Map<Integer, List<Integer>> holder = new HashMap<>();
    for (List<Integer> input : inputs) {
      // storing it in bidirectional way in the map
      List<Integer> l =
          holder.containsKey(input.get(0)) ? holder.get(input.get(0)) : new ArrayList<Integer>();
      l.add(input.get(1));
      holder.put(input.get(0), l);

      List<Integer> l1 =
          holder.containsKey(input.get(1)) ? holder.get(input.get(1)) : new ArrayList<Integer>();
      l1.add(input.get(0));
      holder.put(input.get(1), l1);
    }
    System.out.println(holder);

    // use holder map to get the smaller group here?

    return count;
  }

看来我需要在这里使用递归来获得更小的组?

【问题讨论】:

标签: java algorithm data-structures hashmap


【解决方案1】:

有没有更好的方法来解决这个问题?

更好的方法是使用disjoint-set data structure:

  • 首先,将“朋友组”计算为不相交集数据结构:
    • 初始化一个不相交的数据结构,其中集合的元素将是房间里的人。
    • 对于房间中的每个人 p
      • 调用 MakeSet(p) 以初始化仅包含该人的“朋友组”。
    • 对于每个直接友谊p1p2
      • 调用Union(p1,p2)统一包含 p1 的“朋友组”和包含 p2 的朋友。
  • 接下来,将“朋友组”的大小计算为地图:
    • 初始化一个地图,其中键是房间里的一些人(即他们各自“朋友组”的代表),值是数字(即各种“朋友组”的大小")。
    • 对于房间中的每个人 p1
      • 调用Find(p1)寻找代表p2那个人的“朋友群”。
      • 如果映射尚未包含键 p2 的值,则为该键插入值 0。
      • 增加键 p2 的值。
  • 最后,计算结果:
    • 将结果初始化为较大的值,例如房间里的人数。
    • 对于地图中的每个值(=“朋友组”的大小):
      • 如果该值小于结果,则将结果设置为等于该值。
    • 返回结果。

顺便说一句,您正在执行的操作的技术名称是transitive closure:“是朋友”关系是“直接是朋友”关系的传递闭包。 (但是,维基百科文章中描述的算法对于您的问题并不是最佳的,因为它们没有利用您的关系是 symmetric 的事实。)

【讨论】:

  • 您能否提供一个基于您的建议的示例?我目前无法理解如何解决这个问题?
  • @flash:对不起,我不确定您所说的“示例基础”是什么意思。
  • 我想了解的是如何在这里使用不相交的数据结构来解决这个问题?
  • @flash:正如答案所说:“遍历直接友谊列表;对于每一个,将两个朋友的朋友组联合起来。”
  • @flash,如果您对这个更新后的答案仍然不满意,您能说出原因吗?所以我们可以改进它或生产出更好的。
【解决方案2】:

这是一些代码,出于对您的问题的好奇,我写了一些代码。我对图表了解不多,但它使用递归,就像你要求的那样。

基本上,您会通过输入并为每个人创建一个ArrayList&lt;Integer&gt;。在那个数组中是那个人的直接朋友。例如,1: {6}, for 2: {7, 6}, for 3: {8, 5}。然后,为了获得第 2 个人的所有个朋友,您可以通过将第 7 个人和第 6 个人的数组(不包括重复项)放在一起来创建一个复合 ArrayList&lt;Integer&gt; 数组。因此,递归的使用方式是,函数 getAllFriends(Integer person) 也必须为该人的直接朋友返回 getAllFriends(Integer person2)

因此,代码可能如下所示:

public class Test  {
        public static void main(String[] args) throws Exception {
            String input = "1<->6\n" +
            "2<->7\n" +
            "3<->8\n" +
            "4<->9\n" +
            "2<->6\n" +
            "3<->5";

            HashMap<Integer, ArrayList<Integer>> friends = processInput(input);  //getting data from the input string and storing it in a structured way
            System.out.println(getAllFriends(1, friends, new ArrayList<Integer>(){{add(1);}}));  //output: [1, 6, 2, 7]. Double brackets create an anonymous inner class, you add to the result the id of a person whose friends you're collecting
            }

        public static HashMap<Integer, ArrayList<Integer>> processInput(String input) throws Exception  {
            HashMap<Integer, ArrayList<Integer>> result = new HashMap<>();

            BufferedReader bufReader = new BufferedReader(new StringReader(input));
            String line=null;
            while( (line=bufReader.readLine()) != null )
            {
                Integer personLeft =  Integer.valueOf(line.substring(0, line.indexOf("<")));
                Integer personRight =Integer.valueOf(line.substring(line.indexOf(">")+1, line.length()));

                System.out.println(personLeft + ": " + personRight);

                if (!result.containsKey(personLeft))  {
                    result.put(personLeft, new ArrayList<Integer>());
                }

                result.get(personLeft).add(personRight);

                if (!result.containsKey(personRight))  {
                    result.put(personRight, new ArrayList<Integer>());
                }

                result.get(personRight).add(personLeft);
            }


            return result;

        }

        public static ArrayList<Integer>  getAllFriends(Integer person, HashMap<Integer, ArrayList<Integer>> friends, ArrayList<Integer> result)  {
            for (Integer personFriend: friends.get(person))  {
                    if (!result.contains(personFriend))  {
                        result.add(personFriend);  //add a person, if it wasn't added before
                        getAllFriends(personFriend, friends, result);  //check out that person's friends
                    }
            }

            return result;
        }
}   

【讨论】:

    猜你喜欢
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    相关资源
    最近更新 更多