【问题标题】:Haskell - Generating Subsets of Length kHaskell - 生成长度为 k 的子集
【发布时间】:2018-10-06 10:06:43
【问题描述】:

我有一个计算集合子集的 Haskell 函数。

subsets :: [a] -> [[a]]
subsets [] = [[]]
subsets (x:xs) = [zs | ys <- subsets xs, zs <- [ys, (x:ys)]]

使用示例:

*Main> subsets [1,2,3]
[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

如果我添加定义:

ksubsets k xs = [ys | ys<-subsets xs, length ys==k]

我可以计算一组 n 个元素的子集,其中每个子集恰好有 k 个元素

Example of use:
*Main> ksubsets 3 [1,2,3,4,5]
[[1,2,3],[1,2,4],[1,3,4],[2,3,4],[1,2,5],[1,3,5],[2,3,5],[1,4,5],[2,4,5], 
[3,4,5]]

如何创建一个更有效的函数来生成具有 n 个元素的集合的子集,其中 n 个元素恰好具有 k 个元素,但不生成所有子集。我如何只找到 k 个元素的子集。

【问题讨论】:

标签: haskell


【解决方案1】:

让我们考虑一些递归定义,而无需深入研究代码。

如果您想获取大小为 n 的每个子集,则可以选择一个元素,并将其附加到大小为 n-1 的子集。如果我们对每个元素都这样做,那么我们应该得到所有大小为 n 的子集。这是一个有用的起点!

现在让我们将其放入代码中:

-- A base case:
subsetsOfSize 0 _ = [[]]

-- If there are no elements, there are no subsets:
subsetsOfSize _ [] = []

-- The case discussed above:
subsetsOfSize n (x:xs) =
    [x : subs | subs <- subsetsOfSize (n-1) xs] -- ones starting with x,
    ++ subsetsOfSize n xs                       -- ones starting with other elements.

至于效率?这留给你,因为这看起来有点像你应该自己做的工作。您认为此功能效率低下的地方是什么?以下是一些想法:

  • 如果列表list的长度是m,并且m小于n,那么subsetsOfSize n list = []。我们已经检查了吗?
  • 众所周知,++ 性能不佳。我们可以用什么代替?有没有办法“改写”这个函数?

【讨论】:

  • 这个解决方案是错误的。您假设长度为 n 的没有 x 的子集仅包含 x 后面的元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 2017-01-30
  • 1970-01-01
相关资源
最近更新 更多