我有一个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个元素的子集。
答案 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 = []
的性能不高。我们可以用什么代替呢?有办法“重新定义”此功能吗?