如何找到一组唯一的数组对?

时间:2019-02-24 02:27:44

标签: javascript algorithm coding-efficiency set-theory

假设我有以下数组:

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)蛮力方法,我不知道如何解决这个问题。我认为可能还有另一种更有效的算法。

2 个答案:

答案 0 :(得分: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变得非常大时才变得重要,或者您需要连续重复计算(例如每秒数百万次)。我建议首先优化代码以提高可读性。然后仅在明显需要时进行优化。

答案 1 :(得分:0)

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

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