[经典算法] 排列组合-N元素集合的所有子集(二)
题目说明:
给定一组数字或符号,按照字典序产生所有可能的集合(包括空集合),例如给定1 2 3,则可能的集合为:{}、{1}、{1,2}、{1,2,3}、{1,3}、{2}、{2,3}、{3}。
题目解析:
如果要产生字典顺序,例如若有4个元素,则:
{} => {1} => {1,2} => {1,2,3} => {1,2,3,4} => {1,2,4} => {1,3} => {1,3,4} => {1,4} => {2} => {2,3} => {2,3,4} => {2,4} => {3} => {3,4} => {4}
简单的说,如果有n个元素要产生可能的集合,当依序产生集合时,如果最后一个元素是n,而倒数第二个元素是m的话,
例如:
{a b c d e n}
则下一个集合就是{a b c d e+1},再依序加入后续的元素。
例如有四个元素,而当产生{1 2 3 4}集合时,则下一个集合就是{1 2 3+1},也就是{1 2 4},由于最后一个元素还是4,所以下一个集合就是{1 2+1},也就是{1 3},接下来再加入后续元素4,也就是{1 3 4},由于又遇到元素4,所以下一个集合是{1 3+1},也就是{1 4}。
程序代码:
#include <gtest/gtest.h> using namespace std; void ShowResult(int State[], int nSize) { cout << "{"; for (int i=0; i<nSize; ++i) { cout << State[i] << " "; } cout << "}\n"; } // 产生字典序的子集 int GenerateOrderSubset(int nSize) { if (nSize==0) { cout << "{}" << endl; return 1; } int nCount = 0; int nPos = -1; int *State = new int[nSize]; memset(State, 0, sizeof(int)*nSize); do { nCount++; ShowResult(State, nPos+1); if (nPos==-1) { State[++nPos] = 1; continue; } if (State[nPos] < nSize) // 递增集合个数 { State[nPos+1] = State[nPos] + 1; nPos++; } else if(nPos > 0) // 如果不是第一个位置 { nPos—; // 倒退 State[nPos]++;// 下一个集合尾数 } else { break; // 已倒退至第一个位置 } } while(true); delete[] State; return nCount; } TEST(Algo, tCombination) { // 有字典序 // 0个数子集合数 =〉2^0 = 1 ASSERT_EQ(GenerateOrderSubset(0), 1); // 3个数子集合数 =〉2^3 = 8 ASSERT_EQ(GenerateOrderSubset(3), 8); // 5个数子集合数 =〉2^5 = 32 ASSERT_EQ(GenerateOrderSubset(5), 32); // 10个数子集合数 =〉2^10 = 1024 ASSERT_EQ(GenerateOrderSubset(10), 1024); }
参考引用:
http://www.cnblogs.com/Quincy/p/4838051.html
看书、学习、写代码