设计按发生频率排序的列表

时间:2012-01-10 23:16:25

标签: java design-patterns

设置

我有一对整数列表:((1,2),(1,3),(2,5),(1,6),(2,8),(9,8),( 8,11)等)。在给定对中,数字必须不同,但是当您将列表视为一个整体时,会有很多重复。

虽然这些信息与问题并不严格相关,但每个数字代表一张牌组(并且介于1和52之间),每对代表一名玩家可能的牌。

问题

我们希望对这些数字对进行排序,以便整个列表中包含最频繁卡片的对首先出现。然后这些对按第二个数字排序,按升序排列。然后我们使用列表中的剩余对重复该过程。根据较小数字排在第一位的规则来打破关系。让我们使用上面的列表做一个例子:

  1. 数字1,8和2每个在列表中出现3次,没有数字出现超过3次。因此有一个3路并列,1胜。我们按如下方式构建列表的第一部分:

    (1,2)
    (1,3)
    (1,6)
    
  2. 其余列表项目现为(2,5),(2,8),(9,8),(8,11)。 8出现3次,超过任何其他数字,因此8胜。我们继续如下列表:

    (1,2)
    (1,3)
    (1,6)
    (2,8) <-- Note 2 is the smallest of the "other" numbers amongst the 8 group
    (9,8)
    (8,11)
    (2,5) <-- This gets added in step 3, but since there is only 1 left we add it now
    
  3. 答案标准

    显然我不希望任何人为我编写完整的算法,但我想知道如何最好地设计它,可能还有一些小的伪代码。我的目标是按顺序提高效率,可读性和简单性。

    具体做法是:

    • 我应该使用哪些Collections对象来表示对和整个列表?
    • 我应该在算法开始时获得每个整数的计数,然后通过减去它们来使用它们来更新它们吗?或者我应该在每次通过后重做计数?前者似乎更有效率。
    • 在一个阶段中,通过配对中的“其他”号码进行排序的最佳方法是什么?
    • 关系发生时的排序怎么样?

    感谢您的意见。

1 个答案:

答案 0 :(得分:1)

我认为这不符合设计模式。你需要考虑你的设计,但它必须是一个非常普遍的问题,才有资格作为模式,事实并非如此。

public class CardAndPairs implements Comparable<CardAndPairs> {
    Card card;
    List<Pair> pairs;

    public CardAndPairs(Card card, Set<Pair> allPairs) {
       this.card = card;
       pairs = new HashSet<>();
       for (Pair pair : allPairs) 
         if (pair.contains(card))
           pairs.add(pair);
       // You could then reorder "pairs" by the value of the other card
       // ... see below
    }

    @Override
    public int compareTo(CardAndPairs other) {
       int diff = pairs.size() - other.pairs.size();
       if (diff > 0)
          return 1;
       if (diff == 0)
          return card.compareTo(other.card);
       return 1;
    }
}

然后,您可以将52张卡片的CardAndPairs放入列表中,并使用compareTo自动对其进行排序(隐式使用Collections.sort(list))。

要在上面的构造函数中对给定CardAndPairs内的对进行排序,它会以Java方式进行复杂化。您应该定义一个子类而不是仅使用直接Pair,而不是实现Comparable:

public class PairWithGivenCard 
          extends Pair implements Comparable<PairWithGivenCard> {
   Card givenCard;
   Card otherCard;

   public PairWithGivenCard(Card givenCard, Pair pair) {
      this.givenCard = givenCard;
      for (Card card : pair) // or however you get the cards from pair
         if (card != givenCard)
            otherCard = card;
   }

   @Override
   public int compareTo(PairWithGivenCard otherPair) {
      // It might be a good idea to throw 
      //   some exception if givenCard != otherPair.givenCard
      return otherCard.compareTo(otherPair.otherCard);
   }
}

然后,您需要在List<Pair> pairs的构造函数中更改List<PairWithGivenCard> pairs CardAndPairs。当您将一对添加到列表中时,您必须执行pairs.add(new PairWithGivenCard(card, pair))而不是pairs.add(pair)。最后,您只需在Collections.sort(pairs)的构造函数末尾调用CardAndPairs