What's the quickest way to find all possible pairs in list?

前端 未结 4 787
走了就别回头了
走了就别回头了 2021-01-14 05:03

Basically I have list of players, and I want to pair them up so that each player will play everyone once. What\'s the quickest way to find this data?

相关标签:
4条回答
  • 2021-01-14 05:40

    Such tournament schedule is often called round-robin. In wikipedia, there's also an example of possible scheduling algorithm.

    0 讨论(0)
  • 2021-01-14 05:55

    I put together 2 implementations to compare performance with. The very naive version 1 is about 50% slower than the version 2. That's not to say that nothing faster exists.

    class Program
    {
        class Player
        {
            public string Name { get; set; }
    
            public Player(string name)
            {
                Name = name;
            }
        }
    
        class Match
        {
            public readonly Player Player1;
            public readonly Player Player2;
    
            public Match(Player player1, Player player2)
            {
                Player1 = player1;
                Player2 = player2;
            }
    
            public override string ToString()
            {
                return string.Format("{0} vs. {1}", Player1.Name, Player2.Name);
            }
        }
    
        static readonly List<Player> _players = new List<Player>()
        {
            new Player("John"),
            new Player("Lisa"),
            new Player("Matt"),
            new Player("Dan"),
            new Player("Steve"),
            new Player("Sarah"),
            new Player("Tim")
        };
    
        static void Main(string[] args)
        {
            const int count = 1000000;
    
            {
                var v1 = V1();
                var sw = Stopwatch.StartNew();
                for (int i = 0; i < count; i++)
                {
                    v1 = V1();
                }
                Console.WriteLine(v1);
                Console.WriteLine(sw.Elapsed);
            }
    
            {
                var v2 = V2();
                var sw = Stopwatch.StartNew();
                for (int i = 0; i < count; i++)
                {
                    v2 = V2();
                }
                Console.WriteLine(v2);
                Console.WriteLine(sw.Elapsed);
            }
    
    
            Console.ReadLine();
        }
    
        static List<Match> V1()
        {
            var challengers = new List<Player>(_players);
            var matches = new List<Match>();
            foreach (var player in _players)
            {
                challengers.Remove(player);
                foreach (var challenger in challengers)
                {
                    matches.Add(new Match(player, challenger));
                }
            }
            return matches;
        }
    
        static List<Match> V2()
        {
            var matches = new List<Match>();
            for (int i = 0; i < _players.Count; i++)
            {
                for (int j = i + 1; j < _players.Count; j++)
                {
                    matches.Add(new Match(_players[i], _players[j]));
                }
            }
            return matches;
        }
    }
    
    0 讨论(0)
  • 2021-01-14 05:57

    assuming that players do not appear in the list twice, a double for loop is very quick:

    for (int i=0, i <= playerList.Count - 2, i++)
        for (int j=i+1, j <= playerList.Count - 1, j++)
            //add a new pairing of player i and j
    
    0 讨论(0)
  • 2021-01-14 06:00

    A simple divide and conquer algorithm:

    1. If there are only two people: Pair them and return them.
    2. Otherwise:

      1. Split the group in two groups of equal size.
      2. Find all pairings in each group using this algorithm recursively.
      3. Join the two lists.

        E.g. [[(a,b)]] and [[(c,d)]] becomes [[(a,b),(c,d)]].

      4. Find pairs across of the two groups, by rotating group two.

        E.g. [[(a,c),(b,d)],[(a,d),(b,c)]]

      5. Return (3) + (4)

    This algorithm runs in O(n^2) time, which is optimal, as it generates (n-1) rounds of n/2 pairings.

    For eight players you would get 7 rounds:

    [(a,b), (c,d), (e,f), (g,h)]
    [(a,c), (b,d), (e,g), (f,h)]
    [(a,d), (b,c), (e,h), (f,g)]
    [(a,e), (b,f), (c,g), (e,h)]
    [(a,f), (b,g), (c,h), (e,e)]
    [(a,g), (b,h), (c,e), (e,f)]
    [(a,h), (b,e), (c,f), (e,g)]
    
    0 讨论(0)
提交回复
热议问题