序列中的所有子序列
题目
对于一个序列,如{1, 2, 3, 4, 5}
,求其所有子序列,如{1}
、{1, 2}
、{1, 3, 5}
等等。
解法
对于一个长度为n的序列,其所有子序列的个数为2^n - 1,规模呈指数级增长,所以在此探讨长度不大于32的序列。因此,可以采用位图的方法来解决该问题,利用int型变量作为位图。
如上题中,可以用10000来表示取{1}
,用11000来表示取{1, 2}
,用{10101}
来表示取{1, 3, 5}
。因此,00001~11111之间的数表示原序列的一个子序列,故而可以依次遍历范围00001至11111,得出所有子序列。
代码
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
class SubSeqGenerator
{
private:
vector<T> m_ordinarySeq;
// 子序列总数
int m_seqCount;
// 例如m_mark从00001到11111
int m_mark;
// 掩码长度
int m_markLen;
public:
SubSeqGenerator(const vector<T> &seq)
: m_ordinarySeq(seq)
{
int len = seq.size();
m_seqCount = 1 << len;
m_mark = 1;
m_markLen = len;
}
// 是否还有子序列
bool hasNext() const
{
return (m_mark < m_seqCount);
}
// 返回下一个子序列
vector<T> next()
{
vector<T> subSeq;
for (int i = 0; i < m_ordinarySeq.size(); i++)
{
if (isOneAtBitForMark(i))
subSeq.push_back(m_ordinarySeq[i]);
}
++m_mark;
return subSeq;
}
private:
// m_mark从高位到低位的索引index位置上是否为1
bool isOneAtBitForMark(int index) const
{
int result = m_mark & (1 << (m_markLen - index - 1));
return (result == 0) ? false : true;
}
};
// 打印整型序列
void printSeq(const vector<int> &seq){
cout << "[ ";
for (auto i : seq)
{
cout << i << " ";
}
cout << "]" << endl;
}
int main()
{
vector<int> seq = {1, 2, 3, 4};
SubSeqGenerator<int> generator(seq);
while (generator.hasNext())
{
printSeq(generator.next());
}
return 0;
}