You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现锦标赛多组对阵生成函数?保证每组队伍仅参赛一次

实现思路与代码示例

你的需求本质是单循环赛制的轮次编排——把所有两两对阵分成若干轮,每轮中每个队伍仅参与一场比赛,且所有轮次覆盖全部可能的对阵。下面给两种可行的实现方案:

方案一:固定轮次编排法(高效推荐)

这是体育赛事中常用的单循环编排方式,适合偶数队伍的场景,不需要依赖getMeetingsPossibilities,直接生成轮次,效率最高。

核心逻辑:

  • 固定一支队伍(比如编号0),剩余队伍按顺时针/逆时针轮换位置,每轮生成一组配对:
    1. 把队伍列表分成前后两半,第一轮让前半部分和后半部分对应位置配对
    2. 除固定队伍外,其他队伍轮换一个位置,重复配对直到生成所有轮次(m支队伍最多有m-1轮)

代码实现:

function getSetsOfMeetings(teamCount) {
  if (teamCount % 2 !== 0) {
    throw new Error("仅支持偶数队伍数,奇数队伍需处理轮空逻辑");
  }
  const rounds = [];
  const teams = Array.from({ length: teamCount }, (_, i) => i);
  // 固定第一个队伍,剩余队伍用于轮换
  const fixedTeam = teams[0];
  let rotatingTeams = teams.slice(1);

  for (let i = 0; i < teamCount - 1; i++) {
    const currentRound = [];
    // 固定队伍和轮换组的第一个配对
    currentRound.push(`${fixedTeam}-${rotatingTeams[0]}`);
    // 剩余队伍两两配对(前后对应)
    for (let j = 1; j < rotatingTeams.length / 2; j++) {
      const left = rotatingTeams[j];
      const right = rotatingTeams[rotatingTeams.length - j];
      currentRound.push(`${left}-${right}`);
    }
    rounds.push(currentRound);
    // 轮换:把最后一个元素移到最前面(顺时针轮换)
    rotatingTeams = [rotatingTeams.pop(), ...rotatingTeams.slice(0, -1)];
  }
  return rounds;
}

// 测试4支队伍
console.log(getSetsOfMeetings(4));
// 输出:[ ['0-1','2-3'], ['0-3','1-2'], ['0-2','3-1'] ]

方案二:回溯法(适合理解逻辑)

如果一定要基于getMeetingsPossibilities的结果来生成轮次,可以用回溯法:每轮构建时,跟踪已使用的队伍,确保每个队伍只选一次,完成一轮后从候选对阵中移除已用的对阵,再构建下一轮。

代码实现:

// 假设已有getMeetingsPossibilities函数
function getMeetingsPossibilities(teamCount) {
  const matches = [];
  for (let i = 0; i < teamCount; i++) {
    for (let j = i + 1; j < teamCount; j++) {
      matches.push(`${i}-${j}`);
    }
  }
  return matches;
}

function getSetsOfMeetings(teamCount) {
  const allMatches = [...getMeetingsPossibilities(teamCount)];
  const rounds = [];
  const totalRounds = teamCount - 1;

  while (rounds.length < totalRounds) {
    const currentRound = [];
    const usedTeams = new Set();
    // 遍历剩余候选对阵,挑选不重复队伍的配对
    for (let i = 0; i < allMatches.length; ) {
      const match = allMatches[i];
      const [teamA, teamB] = match.split('-').map(Number);
      if (!usedTeams.has(teamA) && !usedTeams.has(teamB)) {
        currentRound.push(match);
        usedTeams.add(teamA);
        usedTeams.add(teamB);
        // 从候选中移除已用对阵
        allMatches.splice(i, 1);
      } else {
        i++;
      }
    }
    rounds.push(currentRound);
  }
  return rounds;
}

// 测试4支队伍
console.log(getSetsOfMeetings(4));
// 输出:[ ['0-1','2-3'], ['0-2','1-3'], ['0-3','1-2'] ]

关键注意点

  • 若队伍数为奇数,需要额外处理轮空逻辑(每轮让一支队伍轮空)
  • 方案一的效率远高于方案二,尤其是队伍数量较多时,推荐使用方案一

内容的提问来源于stack exchange,提问作者Johan Testas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 00:10:16