[经典算法] 排列组合-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

 

  看书、学习、写代码

转载于:https://www.cnblogs.com/Quincy/p/4838359.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值