安排一对

时间:2017-12-20 22:59:23

标签: java list arraylist

我有一个对的列表(从1到n的组合),我试图将它们安排在不同的列表中,以便列表的所有对都有不同的元素。

实施例

输入:

[(1, 2),(1, 3),(1, 4),(1, 5),(1, 6),(2, 3),(2, 4),(2, 5),
 (2, 6),(3, 4),(3, 5),(3, 6),(4, 5),(4, 6),(5, 6)]

输出:

  

l1:[(1,2)(3,4)(5,6)]

     

l2:[(1,3)(2,5)(4,6)]

     

l3:[(1,4)(2,6)(3,5)]

     

14:[(1,5)(3,6)(2,4)]

     

15:[(1,6)(4,5)(2,3)]

public static HashMap<Integer, ArrayList<Pair<String, String>>> roundTeams(ArrayList<Pair<String, String>> allPairs) {
    HashMap<Integer, ArrayList<Pair<String, String>>> roundTeams = new HashMap<Integer, ArrayList<Pair<String, String>>>();
    int counter = 0;
    while (!allPairs.isEmpty()) {

        ArrayList<Pair<String, String>> c_round = new ArrayList<Pair<String, String>>();

        while (c_round.size() < 3) { // 3 is the length of the output 
                         //list so when using the long list here will be 10
            for (Iterator<Pair<String, String>> iterator = allPairs.iterator(); iterator.hasNext();) {
                Pair<String, String> c = iterator.next();
                if (isValidPair(c, c_round)) {
                    c_round.add(c);
                    iterator.remove();
                }
            }
            if (c_round.size() < 3) {    // same here 
                Pair<String, String> a = c_round.get(c_round.size() - 1);
                c_round.remove(a);
                allPairs.remove(a);
                allPairs.add(a);
            }

        }
        roundTeams.put(counter, c_round);
        counter++;

    }
    return roundTeams;

}

public static boolean isValidPair(Pair<String, String> pair, ArrayList<Pair<String, String>> pairs) {

    if (pairs.isEmpty()) {
        return true;
    }
    for (Pair<String, String> c_pair : pairs) {
        if (c_pair.getKey().equals(pair.getKey()) || c_pair.getValue().equals(pair.getValue())
                || c_pair.getKey().equals(pair.getValue()) || c_pair.getValue().equals(pair.getKey())) {
            return false;

        }
    }
    return true;
}

我已经完成了它,但只有当我使用像上面这样的小输入时它才有效。 如果我把一个更大的输入放在一个下面,那么它会进行无限循环。

  

(1,2)(1,3)(1,4)(1,5)(1,6)(1,7)(1,8)(1,9)(1,10)(1) ,   11)(1,12)(1,13)(1,14)(1,15)(1,16)(1,17)(1,18)(1,19)   (1,20)(2,3)(2,4)(2,5)(2,6)(2,7)(2,8)(2,9)(2,10)(2,   11)(2,12)(2,13)(2,14)(2,15)(2,16)(2,17)(2,18)(2,19)   (2,20)(3,4)(3,5)(3,6)(3,7)(3,8)(3,9)(3,10)(3,11)(3,   12)(3,13)(3,14)(3,15)(3,16)(3,17)(3,18)(3,19)(3,20)   (4,5)(4,6)(4,7)(4,8)(4,9)(4,10)(4,11)(4,12)(4,13)(4,   14)(4,15)(4,16)(4,17)(4,18)(4,19)(4,20)(5,6)(5,7)(5,   8)(5,9)(5,10)(5,11)(5,12)(5,13)(5,14)(5,15)(5,16)(5,   17)(5,18)(5,19)(5,20)(6,7)(6,8)(6,9)(6,10)(6,11)(6,   12)(6,13)(6,14)(6,15)(6,16)(6,17)(6,18)(6,19)(6,20)   (7,8)(7,9)(7,10)(7,11)(7,12)(7,13)(7,14)(7,15)(7,16)   (7,17)(7,18)(7,19)(7,20)(8,9)(8,10)(8,11)(8,12)(8,13)   (8,14)(8,15)(8,16)(8,17)(8,18)(8,19)(8,20)(9,10)(9,   11)(9,12)(9,13)(9,14)(9,15)(9,16)(9,17)(9,18)(9,19)   (9,20)(10,11)(10,12)(10,13)(10,14)(10,15)(10,16)(10,17)   (10,18)(10,19)(10,20)(11,12)(11,13)(11,14)(11,15)(11,   16)(11,17)(11,18)(11,19)(11,20)(12,13)(12,14)(12,15)   (12,16)(12,17)(12,18)(12,19)(12,20)(13,14)(13,15)(13,   16)(13,17)(13,18)(13,19)(13,20)(14,15)(14,16)(14,17)   (14,18)(14,19)(14,20)(15,16)(15,17)(15,18)(15,19)(15,   20)(16,17)(16,18)(16,19)(16,20)(17,18)(17,19)(17,20)   (18,19)(18,20)(19,20)

我的代码非常混乱,可能很难弄清楚什么是错的,所以你能告诉我任何其他方法来解决这个问题吗? 谢谢。

2 个答案:

答案 0 :(得分:1)

您在while (c_round.size() < n)循环中遇到问题。这种情况的问题是当c_round.size()&lt;时,它将无限循环。 n在少数情况下可能发生。当你只有五支球队时,可以考虑3号轮。每轮只能有两场比赛。

如果球队的数量较多,当最后一轮比赛剩下的比赛太少时,你可能会遇到类似的情况。

要解决这个问题,你必须标记这种情况并摆脱循环。

以下是一个示例。 9支球队的输出和4轮的轮次是

Number of teams: 9
Max Round Size: 4
Possible Combinations (36 total)
(1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (1,8) (1,9) 
(2,3) (2,4) (2,5) (2,6) (2,7) (2,8) (2,9) 
(3,4) (3,5) (3,6) (3,7) (3,8) (3,9) 
(4,5) (4,6) (4,7) (4,8) (4,9) 
(5,6) (5,7) (5,8) (5,9) 
(6,7) (6,8) (6,9) 
(7,8) (7,9) 
(8,9) 

Rounds
0: (1,2) (3,4) (5,6) (7,8) 
1: (1,3) (2,4) (5,7) (6,8) 
2: (1,4) (2,3) (5,8) (6,7) 
3: (1,5) (2,6) (3,7) (4,8) 
4: (1,6) (2,5) (3,8) (4,7) 
5: (1,7) (2,8) (3,5) (4,6) 
6: (1,8) (2,7) (3,6) (4,5) 
7: (1,9) 
8: (2,9) 
9: (3,9) 
10: (4,9) 
11: (5,9) 
12: (6,9) 
13: (7,9) 
14: (8,9) 

这是代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.lang3.tuple.Pair;

public class roundTeams {

    public static HashMap<Integer, ArrayList<Pair<String, String>>> roundTeams(ArrayList<Pair<String, String>> allPairs) {

        HashMap<Integer, ArrayList<Pair<String, String>>> roundTeams = new HashMap<Integer, ArrayList<Pair<String, String>>>();
        int counter = 0;

        while (!allPairs.isEmpty()) {

            ArrayList<Pair<String, String>> c_round = new ArrayList<Pair<String, String>>();

            boolean fullRound = false;
            while (!fullRound) { 
                for (Iterator<Pair<String, String>> iterator = allPairs.iterator(); iterator.hasNext();) {
                    Pair<String, String> c = iterator.next();
                    if (isValidPair(c, c_round)) {
                        c_round.add(c);
                        iterator.remove();
                        if (c_round.size() == MAX_ROUND_SIZE) {
                            fullRound = true;
                            break;
                        }
                    }
                }
                // There are no other matches. We're done. 
                fullRound = true;
            }
            roundTeams.put(counter, c_round);
            counter++;
        }
        return roundTeams;
    }

    public static boolean isValidPair(Pair<String, String> pair, ArrayList<Pair<String, String>> pairs) {

        if (pairs.isEmpty()) {
            return true;
        }
        for (Pair<String, String> c_pair : pairs) {
            if (c_pair.getKey().equals(pair.getKey()) || c_pair.getValue().equals(pair.getValue())
                    || c_pair.getKey().equals(pair.getValue()) || c_pair.getValue().equals(pair.getKey())) {
                return false;
            }
        }
        return true;
    }

    final static int MAX_ROUND_SIZE = 4;
    final static int NUM_TEAMS = 8;

    public static void main(String[] args) {

        ArrayList<Pair<String, String>> allPairs = new ArrayList();
        Pair<String, String> pair;

        System.out.printf("Number of teams: %s\nMax Round Size: %s\n", NUM_TEAMS, MAX_ROUND_SIZE);
        System.out.printf("Possible Combinations (%S total)\n", NUM_TEAMS*(NUM_TEAMS-1)/2  );
        for (int i=1; i < NUM_TEAMS; i++) { // First index never reaches the number Teams
            for (int j=i+1; j <= NUM_TEAMS; j++) {
                pair = Pair.of(""+i, ""+j);
                allPairs.add(pair);
                System.out.print(pair + " ");
            }
            System.out.print("\n");
        }
        System.out.print("\nRounds\n");

        HashMap<Integer, ArrayList<Pair<String, String>>> rounds = roundTeams(allPairs);

        for (int i = 0; i < rounds.size(); i++) {
            System.out.print(i + ": ");
            for (Pair<String,String> match : rounds.get(i)) {
                System.out.print(match + " ");
            }
            System.out.print("\n");
        }
    }
}

答案 1 :(得分:1)

这是另一种不同的方法。尝试使用try-test算法优化此问题会以指数方式增加计算负荷。最多12个团队的解决方案很容易,但随后程序开始陷入困境。有一种直接的方法来获得O(n)复杂度的答案。

考虑到有一组固定的团队,每个团队每轮出现一次,所有行都是其他团队的一些排列。这种排列的模式并不难找。考虑这种模式来寻找第3轮:

Round 1 before:                   [(1,2), (3,4), (5,6), (7,8), (9,10)]
Round 1 after transform:          [(1,2), (4,3), (6,5), (8,7), (10,9)]
Round 1 after swap (new round 3): [(1,4), (2,6), (3,8), (5,10), (7,9)]

从第一轮开始,第2轮只是一个&#34;交换&#34;相邻对上的左/右元素。第3轮基于第1轮,是#34;变换&#34;或交换除第一个以外的所有对的左/右元素,然后交换。二十支球队的输出是:

1: [(1,2), (3,4), (5,6), (7,8), (9,10), (11,12), (13,14), (15,16), (17,18), (19,20)]
2: [(1,3), (2,5), (4,7), (6,9), (8,11), (10,13), (12,15), (14,17), (16,19), (18,20)]
3: [(1,4), (2,6), (3,8), (5,10), (7,12), (9,14), (11,16), (13,18), (15,20), (17,19)]
4: [(1,5), (3,7), (2,9), (4,11), (6,13), (8,15), (10,17), (12,19), (14,20), (16,18)]
5: [(1,6), (4,8), (2,10), (3,12), (5,14), (7,16), (9,18), (11,20), (13,19), (15,17)]
6: [(1,7), (5,9), (3,11), (2,13), (4,15), (6,17), (8,19), (10,20), (12,18), (14,16)]
7: [(1,8), (6,10), (4,12), (2,14), (3,16), (5,18), (7,20), (9,19), (11,17), (13,15)]
8: [(1,9), (7,11), (5,13), (3,15), (2,17), (4,19), (6,20), (8,18), (10,16), (12,14)]
9: [(1,10), (8,12), (6,14), (4,16), (2,18), (3,20), (5,19), (7,17), (9,15), (11,13)]
10: [(1,11), (9,13), (7,15), (5,17), (3,19), (2,20), (4,18), (6,16), (8,14), (10,12)]
11: [(1,12), (10,14), (8,16), (6,18), (4,20), (2,19), (3,17), (5,15), (7,13), (9,11)]
12: [(1,13), (11,15), (9,17), (7,19), (5,20), (3,18), (2,16), (4,14), (6,12), (8,10)]
13: [(1,14), (12,16), (10,18), (8,20), (6,19), (4,17), (2,15), (3,13), (5,11), (7,9)]
14: [(1,15), (13,17), (11,19), (9,20), (7,18), (5,16), (3,14), (2,12), (4,10), (6,8)]
15: [(1,16), (14,18), (12,20), (10,19), (8,17), (6,15), (4,13), (2,11), (3,9), (5,7)]
16: [(1,17), (15,19), (13,20), (11,18), (9,16), (7,14), (5,12), (3,10), (2,8), (4,6)]
17: [(1,18), (16,20), (14,19), (12,17), (10,15), (8,13), (6,11), (4,9), (2,7), (3,5)]
18: [(1,19), (17,20), (15,18), (13,16), (11,14), (9,12), (7,10), (5,8), (3,6), (2,4)]
19: [(1,20), (18,19), (16,17), (14,15), (12,13), (10,11), (8,9), (6,7), (4,5), (2,3)]

以下是代码:

import java.util.ArrayList;
import java.util.HashMap;

import org.apache.commons.lang3.tuple.Pair;

public class roundTeams {

    public static HashMap<Integer, ArrayList<Pair<String, String>>> buildRounds(int numberOfTeams) {

        if (numberOfTeams % 2 != 0  ) {
            throw new IllegalArgumentException("An even number of teams is required");
        }

        HashMap<Integer, ArrayList<Pair<String, String>>> roundTeams = new HashMap<Integer, ArrayList<Pair<String, String>>>();

        // Build first round
        ArrayList<Pair<String, String>> round = new ArrayList<Pair<String, String>>();
        for (int i=1; i<=numberOfTeams; ) {
            Pair<String, String> pair = Pair.of(""+i++, ""+i++);
            round.add(pair);
        }
        roundTeams.put(0,round);

        // Build other rounds
        int numberOfRounds = (numberOfTeams - 1);
        for (int i=1; i<numberOfRounds; i++) {
            roundTeams.put(i, transformRound(roundTeams, i));
        }

        return roundTeams;
    }

    /**
     * Create a new round based on existing rounds.
     * @param roundTeams  an array list of rounds. It must have at least one "seed" round.
     * @param i  The zero-based index of the round to add.
     * @return the new round.
     */
    @SuppressWarnings("unchecked")
    private static ArrayList<Pair<String, String>> transformRound(
            HashMap<Integer, ArrayList<Pair<String, String>>> roundTeams,
            int i) {

        if (roundTeams.isEmpty())
            throw new IllegalArgumentException("roundTeams is empty. It must have at least one seed round.");

        ArrayList<Pair<String, String>> round = new ArrayList<Pair<String, String>>();

        if (i>1) {
            // Clone is important here as we will be changing the round values to
            // create a new round and don't want to change the old values.
            round = (ArrayList<Pair<String, String>>) roundTeams.get(i-2).clone(); 

            // Transform/rotate the elements in pairs 2 on
            for (int j=1; j < round.size(); j++) {
                Pair<String, String> pair = round.get(j);
                String key = pair.getKey();
                String value = pair.getValue();
                pair = Pair.of(value, key);
                round.set(j, pair);
            }
        }
        else {
            // Since there is no "zero" round, the second round is based on the 
            // first/seed round without the transform.
            round = (ArrayList<Pair<String, String>>) roundTeams.get(0).clone();
        }

        // Swap right-left elements in neighboring pairs
        for (int j=1; j < round.size(); j++) {
            Pair<String, String> pair = round.get(j-1);
            String key1 = pair.getKey();
            String value1 = pair.getValue();
            pair = round.get(j);
            String key2 = pair.getKey();
            String value2 = pair.getValue();
            pair = Pair.of(key1, key2);
            round.set(j-1, pair);
            pair = Pair.of(value1, value2);
            round.set(j, pair);
        }
        return round;
    }

    final static int NUM_TEAMS = 20;

    public static void main(String[] args) {

        HashMap<Integer, ArrayList<Pair<String, String>>> rounds = buildRounds(NUM_TEAMS);

        for (int i = 0; i < rounds.size(); i++) {
            System.out.println(i+1 + ": " + rounds.get(i));
        }
    }
}