Haskell-生成长度为k的子集

时间:2018-10-06 01:36:13

标签: haskell

我有一个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个元素的子集。

1 个答案:

答案 0 :(得分:6)

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

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

现在将其放入代码中:

float64

关于效率?这留给您了,因为这看起来确实有点像您应该自己完成的工作。您认为此功能的效率低下吗?这里有一些想法:

  • 如果列表-- 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. 的长度为 m ,并且m小于n,则list。我们已经检查过了吗?
  • 众所周知,subsetsOfSize n list = []的性能不高。我们可以用什么代替呢?有办法“重新定义”此功能吗?