用于分组对象的算法

时间:2015-08-31 10:18:10

标签: java algorithm grouping

我有以下课程:

class Sport {
    private String sportsName;
    private List<People> peopleWhoPlayThisSport;
    //...
}
class People {
    private String name;
    private long uniqueId;
   // ...
}

我的输入是一个运动对象列表,为简单起见,请考虑以下示例:

sport1 - Football,   <Sam, Dylan>
sport2 - Basketball, <Tyler, John>
sport3 - Baseball,   <Carter, Dylan>
sport4 - Hockey,     <Kane, Michael>
sport5 - Soccer,     <Carter, Frank>

我必须创建一个List<List<>>,这样内部列表就是拥有至少一个普通玩家的所有体育项目(此处适用传递属性)。在上面的例子中,输出应为

<<sport1,sport3,sport5> , <sport2> , <sport4>>

有关解决此问题和/或伪代码的任何建议吗?

4 个答案:

答案 0 :(得分:6)

听起来像是图形问题。 我要做的是:

  1. 创建一个图表(无向),其中人是节点,到目前为止没有边
  2. 我会经历体育运动,对于每项运动,如果他们玩同样的运动,我会在人与人之间做一个优势(例如,当处理运动1时,它会在Sam和Dylan之间产生优势,当处理运动3时,它会做边缘迪伦和卡特之间)
  3. 作为最后一步,我将采用最终图表的组成部分(在你的例子中Sam-Dylan-Carter-Frank,Kane-Michael,Tyler-John)和#34;将运动应用于他们&#34; - 这意味着对于组件中的每个男孩/女孩,我会将他/她所做的所有运动添加到内部&#34;列表(我更喜欢Set,所以每项运动都有一次)。
  4. 因此图表会以这种方式增长:

    1. 处理足球: Sam-Dylan
    2. 处理篮球:Sam-Dylan, Tyler-John
    3. 加工棒球:Sam-Dylan- Carter ,Tyler-John
    4. 处理曲棍球:Sam-Dylan-Carter,Tyler-John, Kane-Michael
    5. 处理足球:Sam-Dylan-Carter- Frank ,Tyler-John,Kane-Michael
    6. 并且&#34;运用体育&#34; :

      1. Sam(足球),Dylan(足球,棒球),Carter(棒球,足球),Frank(足球)=&gt; (足球,棒球,足球)
      2. 泰勒(篮球),约翰(篮球)=&gt; (篮球)
      3. 凯恩(曲棍球),迈克尔(曲棍球)=&gt; (冰球)
      4. ==&GT; (足球,棒球,足球),(篮球),(曲棍球)

        修改 您可以选择优化每个组件的算法,您将记住与之相关的运动。换句话说,在创建边缘时,您将为该组件的运动集合添加运动。然后&#34;运动&#34;步骤不再需要。一个简单的规则,当两个组件连接时,您将在添加新运动之前结合运动系列。然后算法会去:

        1. 处理足球: Sam-Dylan(足球)
        2. 处理篮球:Sam-Dylan(足球), Tyler-John(篮球)
        3. 加工棒球:Sam-Dylan- Carter (足球,棒球),Tyler-John(篮球)
        4. 处理曲棍球:Sam-Dylan-Carter(足球,棒球),Tyler-John(篮球), Kane-Michael(曲棍球)
        5. 处理足球:Sam-Dylan-Carter- Frank (足球,棒球,足球),Tyler-John(篮球),Kane-Michael(曲棍球)
        6. 请注意,图表的使用不是必需的。您仍然可以使用简单的集合,但图表似乎是最干净的方法和算法最佳方式。它还允许进一步的可扩展性,因为它以自然的方式对数据进行建模 - 例如,您可以进一步找出Sam与Carter在一起的原因(因为他们的共同朋友Dylan与他们两人一起玩不同的运动)。

答案 1 :(得分:0)

Create HashMap<People, List<Sport>> pList
for each Sport s in sportList
   for each People p in peopleWhoPlayThisSport 
      if p present in pList,
          pList.get(p).add(s)      
      else,
          pList.put(p,s)

Iterate on pList 
    If list size of Sport Objects for a People > 1
        Add to Set of Sport Objects which have at least 1 common 


Create another Set from first sportList
Do a Set minus to get Sports without any common player        

答案 2 :(得分:0)

我用@Somabrata所说的类似方法完成了这项工作。

memusg /usr/bin/php -f test.php >output.png

答案 3 :(得分:0)

我为你实现了代码。如果你看到方法“组”,你就明白了。所以这些不需要伪代码。 输出将是:

  <[足球,棒球,足球],[篮球],[曲棍球]]

我还添加了一个新条目:

  

sport6 - 手球,&lt;泰勒,礼萨&gt;

测试多个公共列表的算法。输出将是:

  <[足球,棒球,足球],[篮球,手球],[曲棍球]]

以下是代码:

public class GroupObjects {
int uniqueIdCounter = 1;

People p1 = new People("Sam",uniqueIdCounter++);
People p2 = new People("Dylan",uniqueIdCounter++);
People p3 = new People("Tyler",uniqueIdCounter++);
People p4 = new People("John",uniqueIdCounter++);
People p5 = new People("Carter",uniqueIdCounter++);
People p6 = new People("Kane",uniqueIdCounter++);
People p7 = new People("Michael",uniqueIdCounter++);
People p8 = new People("Frank",uniqueIdCounter++);
People p9 = new People("Reza",uniqueIdCounter++);


Sport s1 = new Sport("Football", Arrays.asList(p1,p2));
Sport s2 = new Sport("Basketball", Arrays.asList(p3,p4));
Sport s3 = new Sport("Baseball", Arrays.asList(p5,p2));
Sport s4 = new Sport("Hockey", Arrays.asList(p6,p7));
Sport s5 = new Sport("Soccer", Arrays.asList(p5,p8));
Sport s6 = new Sport("Handball", Arrays.asList(p3,p9));

List<Sport> sports = Arrays.asList(s1,s2,s3,s4,s5,s6);

public List<List<Sport>> group(List<Sport> sports){
    List<List<Sport>> answerList = new ArrayList<>();
    while (!sports.isEmpty()) {
        List<Sport> common = new ArrayList<>();
        List<Sport> toBeRemoved = new ArrayList<>();
        List<People> people = new ArrayList<>();
        people.addAll(sports.get(0).getPeopleWhoPlayThisSport());
        common.add(sports.get(0));
        toBeRemoved.add(sports.get(0));
        for (int i = 1; i < sports.size(); i++) {
            for (People p : sports.get(i).getPeopleWhoPlayThisSport()) {
                if (people.contains(p)) {
                    people.addAll(sports.get(i).getPeopleWhoPlayThisSport());
                    common.add(sports.get(i));
                    toBeRemoved.add(sports.get(i));
                    break;
                }
            }
        }
        sports = sports.stream().filter(sp->!toBeRemoved.contains(sp)).collect(Collectors.toList());
        answerList.add(common);
    }
    return answerList;
}
public static void main(String[] args) {
    GroupObjects groupObjects = new GroupObjects();
    List<List<Sport>> answer = groupObjects.group(groupObjects.sports);
    System.out.println(answer);
}

class Sport {
...

@Override
public String toString() {
    return sportsName;
}

另请注意,我在代码中使用了Java-8 Streams API。因此,如果您不使用Java-8,请更改该行。

祝你好运!