摘要
刚刚完成一篇利用位运算高效地、巧妙地来解决求组合的博文:《非常给力:位运算求组合》。巧合的是,我在《数据结构算法与应用》一书中看到一道课后题是:用递归实现求一个集合的所有子集。受到题目的要求,我开始想递归,想着想着,我就发现此题不用递归而用位运算来求解,仍然非常巧妙!本篇,我将讲解如何利用位运算来求解集合的所有子集,个人认为这种方法简单、易懂,而且高效!欲知详情,请看下文:
前奏
最近一直在关注位运算及其应用,并完成了多篇博文,其中《非常给力:位运算求组合》是一篇非常值得阅读的一篇,它是我将POJ上的一道水题跟求组合的问题结合而成的。在此力荐各位朋友看看那篇博文。一方面,我正是在完成那篇博文的基础上想到本篇即将要介绍的求子集的方法的,可以说要是没有撰写那篇博文的经历,我根本无法想到本篇的方法;另一方面,本篇应用了那篇博文的很多知识点,这些东西由于在那篇博文中已经介绍过,因此本篇直接利用之,如果您阅读时有不解之处,那么请先阅读那篇博文。
入题
编写算法求一个集合的所有子集,比如集合set={a,b,c,d}的所有子集是:
{},
{a}, {b}, {c}, {d},
{a, b}, {a, c}, {a, d}, {b, c}, {b, d}, {c, d},
{a, b, c}, {a, b, d}, {a, c, d}, {b, c, d},
{a, b, c, d}
一共16个,事实上n个元素的集合的子集共有2n个(包含空集)。
攀亲
事实上“求集合的子集”跟“求组合”是亲缘关系。为什么呢?首先,集合set={s1,s2,……sn}的所有子集可以看做是由多组子集组成的,这些集合组是:
包含0个元素的子集(空集)
包含1个元素的子集
……