O(N)中某场比赛的冠军和O(NLogN)中玩家的排名

Winner of a tournament in O(N) and rank of the players in O(NLogN)

本文关键字:NLogN 玩家 冠军      更新时间:2023-10-16

在N名选手的网球锦标赛中,每个选手都与其他选手比赛。下面的条件总是成立如果参与人P1在与P2的比赛中获胜,并且参与人P2在与P3的比赛中获胜,那么参与人P1也击败了P3。在O(N)时间和O(1)空间内找到冠军。在O(NlogN)时间内找到玩家的排名。我的解决方案:输入是一个布尔矩阵,其中元素矩阵[i][j]表示玩家i是否赢了玩家j。

bool win[][]= {
    {0, 0, 1, 1, 1, 0, 1},
    {1, 0, 1, 1, 1, 1, 1},
    {0, 0, 0, 1, 1, 0, 0},
    {0, 0, 0, 0, 1, 0, 0},
    {0, 0, 0, 0, 0, 0, 0},
    {1, 0, 1, 1, 1, 0, 1},
    {0, 0, 1, 1, 1, 0, 0}
};

所以获胜者可以像这样找到,

int winner = 0;
for (int i = 1; i < PLAYER_COUNT; ++i) {
    if (win[i][winner])
        winner = i;
}
return winner;

对于获得玩家的排名,我想拓扑排序将是一个很好的方法。如果参与人1赢了参与人2,那么就会增加一条边P1-> P2。如果参与人1是赢家,那么它就会比其他参与人都有边。然后拓扑排序获胜者作为源顶点,将给出球员的排名。我的解决方法正确吗?还有其他有效的解决办法吗?

条件

如果玩家P1赢了与P2的比赛并且玩家P2赢了P3

定义了一个全排序,即如果我们为"P2击败P1"定义了P1 < P2,我们就得到了一个传递排序关系<,它可以完全用作排序或查找最大值的规则less-than关系。因此,对于实现,我们可以定义谓词bool lessThan(int p1, int p2),它将简单地在O(1)的矩阵中查找p1p2的关系。然后将谓词用于"最大值"搜索,这是线性的(O(N)),或用于排序(排序),这是O(N log N)

你寻找赢家的方法似乎是正确的。实际上,假设真正的赢家号码是W。当你在循环中拥有i==W时,你将永远拥有win[i][winner]==1,因为玩家W已经打败了其他所有人。因此,您将设置winner=W,并且永远不会更改它,因为没有人赢得W

你的代码也是O(N),所以我认为它解决了第一个问题。

对于第二个问题,是的,拓扑排序可以,但一个简单的实现将是O(N^2)。但是,请注意,win表实际上提供了严格的总顺序。因此,你可以应用任何标准的排序算法,比较两个玩家,看看其中一个是否战胜了另一个。也就是说,只需使用

bool less(int playerA, int playerB) {
    return win[playerA][playerB];
}

in std::sort .

严格全序的概念也为你的算法提供了另一种证明,以找到一个获胜的。

以下是示例的完整代码:http://ideone.com/99DIQk