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

题目说明:

将一组数字、字母或符号进行排列,以得到不同的组合顺序,例如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、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。

由于一个数的全排列就是其本身,从而得到以上结果。

2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。

即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合。

 

程序代码:
#include <gtest/gtest.h>
using namespace std;

// 全排列

void Swap(int* v1, int* v2)
{
    if (v1 == v2)
        return;

    int value = *v1;
    *v1 = *v2;
    *v2 = value;
}

void ShowResult(int data[], int size, int count)
{
    for (int i = 0; i < size; ++i)
    {
        cout << data[i] << " ";
    }

    if (count % 8 == 0)
    {
        cout << endl;
    }
    else
    {
        cout << "  ";
    }
}

void Permutation(int data[], int begin, int end, int& count)
{    
    if (begin < end)
    {
        for (int i = begin; i < end; ++i)
        {
            Swap(&data[begin], &data[i]);
            Permutation(data, begin+1, end, count);
            Swap(&data[begin], &data[i]);
        }
    }
    else
    {
        ++count;
        ShowResult(data, end ,count);
    }
}

TEST(Algo, tPermutation)
{
    int data[] = {1,2,3,4};
    int nCount = 0;

    // 4个数 4! = 24
    Permutation(data, 0, 4, nCount);
    ASSERT_EQ(nCount, 24);

    // 5个数 5! = 120
    int data1[] = {1,2,3,4,5};
    nCount = 0;
    Permutation(data1, 0, 5, nCount);
    ASSERT_EQ(nCount, 120);

    // 6个数 6! = 720
    int data2[] = {1,2,3,4,5,6};
    nCount = 0;
    Permutation(data2, 0, 6, nCount);
    ASSERT_EQ(nCount, 720);
}

 

参考引用:

排列及计算公式:

从n个不同元素中,任取m(m≤n)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号 p(n,m)表示。

p(n,m)=n(n-1)(n-2)……(n-m+1)= n!/(n-m)!(规定0!=1)

 

  看书、学习、写代码

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值