【问题标题】:Return unique set of numbers from a list从列表中返回唯一的一组数字
【发布时间】:2013-12-21 17:55:16
【问题描述】:

给定两个数 m 和 n,m 小于 n,返回一组从 1 到 n 的 m 个随机唯一数。例如,如果您有 m = 6 和 n = 49,这与给出随机彩票号码相同。

这样做的一种方法是使用随机数生成器获取 0 和 1 之间的数字,乘以 n,截断为整数,检查数字是否已经在集合中,如果没有添加到集合中,重复直到我们有 m 个数字.

另一种方法是先创建一个数字1到n的数组,随机重新排列数字,读出前m个数字。

我认为如果 m 比 n 小,第一个更好,例如,如果 m = 1 和 n = 1000000,第一个显然会快得多。但是,如果 m 很大,我认为第二种方法会更好,例如,如果 m = 500000 和 n = 1000000,如果您不断返回已经添加到设置。

我的问题是,是否有一种数学方法可以计算出 m 和 n 之间的关系,以便何时使用一种方法比另一种更有效?

【问题讨论】:

  • 你的“随机重新排列数字”的方法是什么?
  • 这个问题似乎是题外话,因为它是关于概率分析的。 Mathematics 可能更适合这个问题的某些派生版本。
  • @PaulDraper 可能指的是某些语言中的内置函数,例如 shuffle()。
  • 一个提示是,如果 m n/2 我会选择第二个选项。
  • 如果 m 超过 n/2,你当然可以使用第一种方法,但取你的集合中没有出现的数字。例如,如果 m = 90 且 n = 100,则使用该方法获得 10 个数字,然后您的 90 个数字都是其他数字。当 m = n/2 时,第一种方法效率最低。

标签: algorithm


【解决方案1】:

扩展我的评论。让 E[X_i] 是我们选择一个尚未在集合中的元素之前的预期抽奖次数。如果选择不在集合中的东西的概率是p,那么我们有

E[X_i] = 1/p

要看到这一点,认为要么我们选择正确(概率为 p),要么我们没有在这种情况下添加平局,因此

E[X_i] = p + (1 - p) * (1 + E[X_i])

来自E[X_i] = 1/p

现在是第 i 个元素(从 0 开始)p = (n - i) / n,因此是 E[X_i] = n / (n - i)。将所有E[X_i]i < m 相加,我们得到提取m 数字的预期抽奖次数。对于m <= n/2,这显然比创建n 元素列表并对其进行改组要好。

【讨论】:

  • 你如何在最后一行得出结论,这显然比创建列表和改组更好?
  • 嗯,最后一个要选择的元素有 E[X_i] = n / (n - n/2) = 2。这比 n / (n - i) 大,因为 i
  • 你实际上只需要 m 个操作来进行随机播放,因为一旦你有了前 m 个数字,你就可以停止,其余的不需要随机播放。因此,如果 m = n/2 这会更快吗?
  • 好点。不过,我不认为你可以用费舍尔耶茨做到这一点。为此,您需要构建数组 1..n,它本身就是 O(n)。不过很想知道它是否可能:)
【解决方案2】:

我们用time complexity来衡量一个算法,它表示时间成本随着输入大小的增加而增加的速度。

在您的情况下,您的第一个算法将不起作用。生成一个随机数直到它不等于给定的数字有机会花费无限的时间。因此,让我们通过以下方式对其进行一些改进:

  1. 列出所有N个候选号码;
  2. 从1和N生成一个随机数R;
  3. 从列表中选择第 R 个数字;
  4. 从列表中删除选定的号码;令 N 为 N-1;
  5. 转到第2步,直到获得M个选定的号码。

这种改进的算法具有时间复杂度的上限。第 3~4 步的复杂度是 O(M),无论使用线性还是链表。它们将被重复 M 次。该算法的整体复杂度为O(NM)

第二个算法的复杂度是O(N),使用Fisher–Yates shuffle

所以,第二种算法在复杂度上是赢家。请注意,这只是意味着当输入大小增加时,赢家的时间成本增加得更慢。这并不意味着它总是比另一个花费更少的时间我们不通过绝对时间成本来衡量算法,因为它因不同的硬件、系统、语言和编译器等而异。我们采用时间复杂度。

【讨论】:

  • 使用Fisher Yates可以在线性时间内完成洗牌。
  • @sebii 已更新。谢谢。
  • 我认为您提出的这种改进算法是第二种方法的另一种说法。创建所有可能元素的列表,然后随机选择它们与重新排列列表相同。我认为您不能只说第二种方法比第一种方法快,如果 m = 2 和 n = 1000,即使第一种方法可能需要无限时间,它几乎总是比第二种方法快得多
  • 我不会真正将您的“改进”称为改进。原来最好的情况是 O(M)。
  • @user2802557 复杂性用于衡量输入大小增加时时间成本增加的速度,而不是衡量给定输入的时间成本有多少.
【解决方案3】:

如果您从数组 [1,2,...,n] 开始,您可以重复地将第 i 个元素与从 i 到 n 随机选择的位置中的元素交换。对 1

如果 m

这是 O(m)。

【讨论】:

    猜你喜欢
    • 2014-07-09
    • 2022-11-11
    • 1970-01-01
    • 2013-08-24
    • 2020-08-03
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多