cri*_*id9 9 algorithm set combinatorics backtracking
对于一组表格A = {1, 2, 3, ..., n}
.它被称为集合的分区,是A
一组k<=n
尊重以下定理的元素:
a)所有分区的A
并集是A
b)2个分区的交集A
是空集(它们不能共享相同的元素).
例如.A = {1, 2,... n}
我们有分区:
{1, 2, 3}
{1, 2} {3}
{1, 3} {2}
{2, 3} {1}
{1} {2} {3}
这些理论概念在我的算法教科书中提出(顺便说一下,这个子章节是"回溯"章节的一部分).我应该找到一个算法来生成给定集合的所有分区.我整天都在努力解决这个问题,但我找不到解决办法.你能解释一下这个算法是如何工作的吗?另外,你能给我一个算法的伪代码草图吗?
ric*_*ici 20
有一个重要的观察结果(在评论中),一组n
元素的分区可以表示为[ p 1,... p n ] 形式的整数序列,其中p i是元素i的分区号.对于这样的序列是有效的,它必须遵守的规则p 1是1,并且对于每个Ĵ其中1 < Ĵ ≤ Ñ,有一些我 < Ĵ使得p Ĵ ≤ p 我 1.或者换句话说,在序列的任何前缀中,不会跳过整数.
现在,有一种用于按字典顺序枚举约束序列的标准算法,包括以下内容:
关于搜索可递增元素的若干规定,该算法最差O(n),并且当要递增的元素通常接近序列的末尾时通常为O(1).(例如,使用此算法枚举置换是O(1)以找到下一个置换,只要您可以在O(1)中找到"下一个元素".)
为了将此算法应用于分区案例,我们观察以下内容:
说明观察2中的条件的另一种方式是元素是可递增的,除非它的值是n或者它是序列中具有其值的第一个元素.如果我们也保持序列[ m 1,... m n ],其中m 1是0,并且m i是m i -1和p i -1的最大值,我们可以在O(1)中进行该确定.米是微不足道的维护,并且它允许我们重写被简称为incrementability条件p 我 ≤ 中号我.
很容易看出Next Partition可以在O(n)时间内实现,但是当它发生时,它也是分摊时间O(1)的情况.粗略地说,这是因为在大多数情况下,序列的最后一个元素是可递增的.
如果您的集合不大(或者使用堆栈),您可以尝试递归答案:
原理如下,你有一个返回的函数:
rec_func(SET) = List of List of Set
Run Code Online (Sandbox Code Playgroud)
并按如下方式工作:
rec_func(SET) =
if SET = {empty}:
// if no element, easy to give the answer
return([[]])
else:
// 1. Remove one element from the set : 'a' to this set
a = SET.pop()
// 2. Call rec_func :
list_of_list_of_set = rec_func(SET\'a')
response = []
// 3. For every possibilities given by the function add the element 'a' :
For every list_of_set in list_of_list_of_set :
// Case 1, you add 'a' to list_of_set
response.push( [{'a'} + list_of_set] )
// Case 2, for every set, you create a copy where you add 'a'
for every set in list_of_set:
response.push( [{set,'a'} + list_of_set\set] )
// The function return the list of list of set created.
return(response)
Run Code Online (Sandbox Code Playgroud)