假设我有一个数字范围,例如{2,3,4,5},以std::vector v
的顺序存储,并且我想列出所有可能的子集,以5结尾使用STL。 ..那就是:
2 3 4 5
2 3 5
2 4 5
3 4 5
2 5
3 5
4 5
5
(我希望我不要忘记任何:))
我尝试使用while(next_permutation(v.begin(),v.end()))
,但未提出想要的结果:)
有没有人有想法?
PS:那些已经完成谷歌代码堵塞2010年档案的人可能会认识到这一点:)
答案 0 :(得分:6)
让我们关注打印所有子集的问题。如您所知,如果您有n
个元素的向量,则可能有2^n
个可能的子集。并非巧合,如果您有n
位整数,则最大存储值为2^n
。如果将每个整数视为位向量,则迭代所有可能的值将给出所有可能的位子集。好吧,我们通过迭代整数来免费获得子集!
假设向量不超过32个元素(超过40亿个可能的子集!),这段代码将打印向量v
的所有子集(不包括空元素):
for (uint32_t mask =1; mask < (1<<v.size()); ++mask)
{
std::vector<int>::const_iterator it = v.begin();
for (uint32_t m =mask; m; (m>>=1), ++it)
{
if (m&1) std::cout << *it << " ";
}
std::cout << std::endl;
}
我只是为vector的大小创建所有可能的位掩码,并遍历每一位;如果它已设置,我打印适当的元素。
现在应用以某个特定数字结尾的规则是小菜一碟(通过在通过掩码循环时检查附加条件)。优选地,如果向量中只有一个 5 ,则可以将其交换到末尾并打印所有向量的子集而不使用最后一个元素。
我实际上正在使用std::vector
,const_iterator
和std::cout
,因此您可能会认为它是使用STL解决的。如果我想出更多STLish,我会告诉你(好吧,但是如何,它只是迭代)。您可以使用此功能作为STL解决方案的基准; - )
编辑:正如JørgenFogh指出的那样,如果你想对大型矢量进行操作,它就无法解决你的子集蓝调问题。实际上,如果您想打印32个元素的所有子集,它将生成数TB的数据。如果你觉得受到常数32的限制,你可以使用64位整数,但你甚至不会遍历所有数字。如果您的问题只是回答了多少个所需的子集,那么您肯定需要另一种方法。 STL也不会有太大帮助; - )
答案 1 :(得分:1)
因为你可以使用任何容器我会使用std :: set,因为它就在我们想要表示的旁边。 现在你的任务是找到所有以5结尾的子集,所以我们采用初始设置并从中删除5。 现在我们想要拥有这个新集合的所有子集,并在最后添加5。
void subsets(std::set<std::set<int>> &sets, std::set<int> initial)
{
if(initial.empty())
return;
sets.insert(initial);//save the current set in the set of sets
std::set<int>::iterator i = initial.begin();
for(; i != initial.end(); i++)//for each item in the set
{
std::set<int> new_set(initial);//copy the set
new_set.erase(new_set.find(*i));//remove the current item
subsets(sets, new_set);//recursion ...
}
}
sets
是一个包含所需子集的集合。
initial
是您希望拥有子集的集合。
最后使用subsets(all_subsets, initial_list_without_5);
这应该创建子集,最后你可以为所有子集追加5。顺便说一下,不要忘记空集:)
另请注意,创建和删除所有这些集合效率不高。如果你想要它更快,最终的集合应该获得指向集合的指针,new_set应该动态分配...
答案 2 :(得分:0)
使用置换来创建向量的向量。然后使用带有函数的std::partition将其排序为以5结尾的向量和不以5结尾的向量。
答案 3 :(得分:0)
tomasz描述的解决方案只要n<=32
就可以使用,尽管非常长时间打印2 ^ 32个不同的子集。由于大数据集的边界是2&lt; = n&lt; = 500,因此产生所有子集绝对不是要走的路。你需要想出一些聪明的方法来避免生成它们。事实上,这是问题的重点。
如果需要,您可以通过Google搜索问题找到解决方案。我的提示是你需要查看集合的结构并避免生成它们。你应该只计算有多少。