【问题标题】:How do I find a set of unique pairs of an array?如何找到一组唯一的数组对?
【发布时间】:2019-02-24 02:27:43
【问题描述】:

假设我有以下数组:

array = [0, 1, 2, ... , n]

如何找到一个集合,使得集合中的对都是唯一且不重复的元素?

这意味着:

• (x, y) = (y, x) 所以如果 (x, y) 在集合中,则 (y, x) 不会在集合中,反之亦然

• 如果某个元素已被使用,则不能再次使用它。

例如:如果 (1,2) 在集合中,则集合中不可能有一对具有 1 或 2。

上下文: 我正在创建一个记忆游戏,将硬币放在 2n 个元素的板上。我希望游戏的每次迭代都将元素放置在板上的随机空间中。

例如:

Suppose I have: [A, B, C, D, E, F]
Since [A, B, C, D, E, F] is length 6, then the board will consist of 12 elements.
My board will look like the following such that the elements were randomly placed:

A B C D

C A F B

E F E D

坦率地说,如果不使用 O(n^2) 蛮力方法,我不知道如何解决这个问题。我认为可能还有另一种更有效的算法。

【问题讨论】:

  • 分享您的代码以显示已尝试,
  • @SagarAgrawal 我的想法是我不知道从哪里开始,我不是在寻找一个完整的算法,而是从哪里开始或者是否有可能的想法
  • 如果您正在创建记忆游戏,您可以简单地创建两个输入数组。从数组中随机逐出元素并将它们随机放置在 3 个输出数组中。
  • 创建 [A, A, B, B, C, C, D, D, E, E, F, F] 并随机播放?
  • @TryKhov:没问题 :) 请注意,您可以就地进行随机播放,因此只有一个数组。

标签: javascript algorithm coding-efficiency set-theory


【解决方案1】:

您可以使用Fisher–Yates shuffle 在 O(n) 时间内有效地洗牌一个包含两个硬币值的数组。该算法基本上采用一个排序列表,并不断交换列表中的两个随机元素,直到列表在数学上被打乱/随机。

在 JavaScript 中:

// Generate seed array.
// Numbers are used here for simplicity, but the array can contain any type like String.
a = [];
for (i=0; i<4; i++) { a.push(i, i); }
console.log(a);  // [0, 0, 1, 1, 2, 2, 3, 3]

// This is the "modern version" pseudo-code ported to JavaScript:
// To shuffle an array a of n elements (indices 0..n-1):
n = a.length;
// for i from n−1 downto 1 do
for (i=n-1; i>0; i--)  {  
  // j ← random integer such that 0 ≤ j ≤ i
  j = Math.floor(Math.random() * (i + 1));

  // exchange a[j] and a[i] 
  tmp = a[j];
  a[j] = a[i];
  a[i] = tmp;
}
console.log(a);  // [2, 1, 3, 3, 0, 1, 0, 2]

旁注: 尽管你的算法中的 O(n^2) 听起来很糟糕,但它可能对你的硬币游戏项目的洗牌没有太大的影响。您只在开始时将少量项目洗牌一次。所以你可能无法判断复杂度是 O(n) 还是 O(n^2)。只有当 n 变得非常大时,复杂性才会变得重要,或者您需要不断重复计算(例如每秒数百万次)。我建议首先优化您的代码以提高可读性。然后只在明显需要时进行优化。

【讨论】:

  • 在 JavaScript 中声明变量很重要。
  • 嗨@Leftium,谢谢你的建议。我奇怪地从之前的建议中想到了类似的东西。我所做的是遍历列表,并用列表中的随机元素切换元素,这基本上就是您刚刚呈现的内容!它可以工作,并且是 O(n),就像我想要的那样。
  • @TryKhov:酷!请注意,该算法的简单版本过度洗牌,因此某些组合比其他组合更常见:不是真正随机的。这就是为什么 Fisher Yates 的设计如此。 medium.com/@oldwestaction/randomness-is-hard-e085decbcbb2
【解决方案2】:

创建两个输入数组(或一个包含重复元素的数组)。从数组中随机逐出元素并将它们随机放置在您的 3 个输出数组中。您无需随机播放它们,因为您可以随机选择元素并随机放置。

在您的代码中,您可以检查,如果在输出数组中,元素是否已经存在或不在给定索引上以避免覆盖。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-08
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多