返回所有可能的匹配配对的算法

发布于 2025-01-21 01:24:48 字数 502 浏览 0 评论 0原文

我有一个 PlayerID 数组,

Players = [ 1, 2, 4, 12, 14, 16 ]

现在需要一个返回所有可能组合的算法,例如

 [1,2], [4,12], [14,16] 
 [1,4], [2,12], [14,16] 
 [1,12], [2,4], [14,16]
 [1,14], [2,4], [12,16]
...and so on, till all combinations have been listed

[1,2] 或 [2,1] 之间没有区别。 我会将 X

我发现了以下方法 [https://stackoverflow.com/a/16256122][1] 这非常接近我所寻找的,但该算法并不对配对进行分组(6 名玩家的数组 = 3 组可能的配对)。

有人可以改进这个算法来满足我的需要吗?

Java、C++、C# 或 PHP 中的示例都很好。

先感谢您!

I have an Array of PlayerIDs

Players = [ 1, 2, 4, 12, 14, 16 ]

I now need an algorithm that returns all possible combinations, like

 [1,2], [4,12], [14,16] 
 [1,4], [2,12], [14,16] 
 [1,12], [2,4], [14,16]
 [1,14], [2,4], [12,16]
...and so on, till all combinations have been listed

There is no difference between [1,2] or [2,1].
I would stay that X<Y at [X,Y]

I found the following approach [https://stackoverflow.com/a/16256122][1] which is really near to what I look for, but this algorithm doesn't group the pairings (Array of 6 Players = Group of 3 possible pairings).

Can somebody refine this algorithm that fits my needs?

Examples in Java, C++, C# or PHP are fine.

Thank you in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

羞稚 2025-01-28 01:24:48

急切评估

我们可以编写choosek(t, k)来从数组或列表中查找大小为k的所有固定长度组合,t。我们可以使用归纳推理来解决问题 -

  1. 如果k为零或负数,没有更多的选择,返回一个空选择的单例列表
  2. (归纳) k 是正数,所以至少有一个选择。如果t为空,则没有任何可供选择的内容,返回空的选择列表。
  3. (归纳)k 为正,t 至少有一个选择。对于子问题 choosek(t.slice(1), k - 1) 的每个 comb,将 t 的第一个元素添加到由此产生的梳子。将此结果连接到第二个子问题 choosek(t.slice(1), k) 的结果。

下面我选择了 JavaScript,因为我可以在答案中嵌入一个功能演示。运行下面的程序来查看 k = 2k = 3 的演示

function choosek(t, k) {
if (k <= 0)
return [[]] // 1
else if (t.length == 0)
return [] // 2
else
return choosek(t.slice(1), k - 1) // 3
.map(comb => [t[0]].concat(comb))
.concat(choosek(t.slice(1), k))
}

console.log(
choosek(["

eager evaluation

We can write choosek(t, k) to find all fixed-length combinations of size k from an array or list, t. We can approach the problem using inductive reasoning -

  1. if k is zero or negative, there are no more choices to make, return a singleton list of the empty choice
  2. (inductive) k is positive so there is at least one thing to choose. If t is empty, there is nothing to choose from, return the empty list of choices.
  3. (inductive) k is positive and t has at least one choice to make. For each comb of the sub-problem choosek(t.slice(1), k - 1), prepend the first element of t to the resulting comb. Concatenate this result to the result of the second sub-problem, choosek(t.slice(1), k).

Below I chose JavaScript because I can embed a functioning demo right here in the answer. Run the program below to see demoes of k = 2 and k = 3

function choosek(t, k) {
  if (k <= 0)
    return [[]]                            // 1
  else if (t.length == 0)
    return []                              // 2
  else
    return choosek(t.slice(1), k - 1)      // 3
      .map(comb => [t[0]].concat(comb))
      .concat(choosek(t.slice(1), k))
}

console.log(
  choosek(["????","????","????","????"], 2).map(comb => comb.join("")).join(", ")
)

console.log(
  choosek(["????","????","????","????"], 3).map(comb => comb.join("")).join(", ")
)

// choose 2
????????, ????????, ????????, ????????, ????????, ????????

// choose 3
????????????, ????????????, ????????????, ????????????

All of the functions used here .map, .concat, and .slice have straightforward counterparts in PHP, Java, Python, and C#.

Notice that choosek returns an array of combinations where each combination is itself an array. This allows the caller to do whatever she/he pleases with each combination. For example, you may wish to convert each to a string for logging in the console or perhaps you will leave them as arrays to build a tournament bracket.

generators

PHP, Python, and C# all support generators, though I'm unsure of Java. Using JavaScript we can demonstrate choosek using generators. The advantage of this approach are numerous -

  1. Generators are lazy, meaning we can pause/resume them. The caller can collect as many combinations as needed, discard the rest, or exhaust the entire generator.

  2. If the input is significantly large, the solution space may be gigantic. Forcing all of the combinations into an array before returning the result could cost a lot of memory. Generators allow you to process the result as each one is being generated.

  3. A generator's results can easily be collected into an array using Array.from or equivalent, if desired, though this is not required. This choice is left for the caller to decide. As a result, the generator implementation reduces one level of nesting arrays, making it easier to read/write the program.

  4. The exact same inductive reasoning approach can be applied to solve the problem

function* choosek(t, k) {
  if (k <= 0)
    return yield []
  else if (t.length == 0)
    return
  else {
    for (const comb of choosek(t.slice(1), k - 1))
      yield [t[0]].concat(comb)
    yield *choosek(t.slice(1), k)
  }
}

for (const comb of choosek(["????","????","????","????"], 2))
  console.log(comb.join(""))

????????
????????
????????
????????
????????
????????

To compute permutations, see this related Q&A.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文