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

  看书、学习、写代码
时间: 2024-11-05 16:07:45

[经典算法] 排列组合-N元素集合的所有子集(二)的相关文章

[经典算法] 排列组合-M元素集合的N个元素子集

题目说明: 假设有个集合拥有m个元素,任意的从集合中取出n个元素,则这n个元素所形成的可能子集有那些? 题目解析: 假设有5个元素的集合,取出3个元素的可能子集如下: {1 2 3}.{1 2 4 }.{1 2 5}.{1 3 4}.{1 3 5}.{1 4 5}.{2 3 4}.{2 3 5}.{2 4 5}.{3 4 5} 这些子集已经使用字典顺序排列,如此才可以观察出一些规则: 如果最右一个元素小于m,则如上面一样的不断加1 如果右边一位已至最大值,则加1的位置往左移 每次加1的位置往左移

[经典算法] 排列组合-全排序

题目说明: 将一组数字.字母或符号进行排列,以得到不同的组合顺序,例如1 2 3这三个数的全排列有:1 2 3.1 3 2.2 1 3.2 3 1.3 1 2.3 2 1. 题目解析: 设一组数p = {r1, r2, r3, - ,rn}, 全排列为perm(p),pn = p – {rn}. 则perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), - , rnperm(pn).当n = 1时perm(p} = r1. 如:求{1, 2, 3, 4, 5}

算法练习:排列组合之子集合

问题描述 输入一个含有不同数字的序列,输出其所有子集合(含空集).要求:1)集合里元素有序排列:2)输出结果不含有重复集合 举例 输入序列{3,1,2} 输出:{},{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3} 问题分析 可以使用排列组合问题求解的第一种方法:分期摊还.初始化时,结果集合里含有一个空集.当扫描数列时,保留原有集合,同时将当前元素插入现有的所在集合中,从而形成新的集合.详见后面代码的GetSubSetsAmortized函数. 也可以使用第二种方法:f

迷人的算法-排列组合

需求 最近工作中碰到一个需求:我们的数据表有多个维度,任意多个维度组合后进行 group by 可能会产生一些”奇妙”的反应,由于不确定怎么组合,就需要将所有的组合都列出来进行尝试. 抽象一下就是从一个集合中取出任意元素,形成唯一的组合.如 [a,b,c] 可组合为 [a].[b].[c].[ab].[bc].[ac].[abc]. 要求如下: 组合内的元素数大于 0 小于等于 数组大小: 组合内不能有重复元素,如 [aab] 是不符合要求的组合: 组合内元素的位置随意,即 [ab] 和 [ba

第一节.排列组合

总结:什么时候用回溯法? 如果题目要求求出所有满足条件的解,一般来说是用回溯法,记住回溯法的模板,对不同的题目只需要修改这个条件即可. 回溯法的本质是在问题的解空间树上做深度优先搜索(DFS).这节课主要讲了四个排列组合的问题,分别是子集,带重复元素的子集,全排列,带重复元素的全排列.本文分析求子集的问题,给出程序模板.       题目:给定一个含不同整数的集合,返回其所有的子集.       样例: 如果 S = [1,2,3],有如下的解: [ [3], [1], [2], [1,2,3]

M个元素集合取出N个不重复排列组合

#include<stdio.h>#include<string.h> int check(char *str, int l){     for(int i=0; i<l ;i++)     {          for(int j=0; j<l ;j++)          {               if(j==i)                continue;               if(str[i]==str[j])               

java排列组合算法代码实现

原文:java排列组合算法代码实现 源代码下载地址:http://www.zuidaima.com/share/1550463479024640.htm java排列组合算法,有需要研究的童鞋可以下载,运行结果如下: package com.zuidaima.test; /** *@author www.zuidaima.com **/ public class Pailie { public static void main(String[] args) { int[] ia = {1, 2,

利用标准库算法求解排列组合

以前求序列的排列时,最常用的方法就是递归回溯,现在发现其实像这样有特定算法的重复性工作是可以在STL标准库中找到答案的. 在STL的变序性算法中,有两个用于排列元素的算法分别如下: bool next_permutation(Iterator beg,Iterator end) bool prev_permutation(Iterator beg,Iterator end) 这两个算法的功能也很简单,next_permutation()会改变区间(beg,end)内的元素次序,使它们符合"下一个

请写一个算法,用于将list集合内重复元素剔除

package Homework; import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Scanner;/** * list集合是否可以包含重复元素? * 如果可以,请写一个算法,用于将list集合内重复元素剔除. * @author 张致远 * */public class Homework2 { public static void main(String[]