实现全排列算法(C++)

本文介绍了如何使用递归算法实现全排列。针对输入的不含重复元素的数组,通过固定当前位置元素并递归处理其余元素,达到全排列的效果。文章讨论了动态数组vector的使用,以及如何处理含重复元素的情况,通过添加`judgeswap`函数避免重复输出。
部署运行你感兴趣的模型镜像

要求:输入任意长度的不含重复元素的数组,打印出该数组的全部全排列。

  1. 方向:考虑使用递归算法
    1.问题可拆成子问题:将n个元素的全排列拆成n-1个元素的全排列。
    2.边界条件(递归的尽头):只有1个元素时,返回该元素本身。
    3.将n个元素全排列拆成n-1个元素全排列,相当于固定了当前元素。

  2. 算法的实现

void perm(vector<int> &a, int head, int end, int n) {
    if (head == end) {
        display(a, n);
        return;
    }
    for (int i = head; i <= end; i++) {
            swap(a, head, i);
            perm(a, head + 1, end, n);
            swap(a, head, i);
    }
}

实例:a={1,2,3}
程序执行过程:

要对1、2、3全排列,先固定住1,对2、3进行全排列
要对2、3全排列,先固定住2,对3进行全排列
要对3进行全排列,但检测到3只有一个元素,于是3排列完毕(就是3)输出当前组合1、2、3,并返回至上一层2、3的全排列
要对2、3全排列,2已经固定过,便将2与3换位,固定3,对2进行全排列
要对2进行全排列,但检测到2只有一个元素,于是输出当前组合1、3、2
2、3也全排列完毕,再返回上一层,对1、2、3进行全排列
1已经固定过,便将1与2换位,对1、3进行全排列…
以此类推,直至最顶端(1、2、3)完成全排列

3.一些遇到的问题

  • 实现用户输入任意数字(无论几个)的全排列:使用动态数组vector容器
    关于vector的一些基本操作:
    基本方法:指路1
    作为函数参数传递:指路2(将动态数组以引用形式传给函数是很重要的,与静态数组不同,将数组名作为参数传入,会被视作值传递,便会发生拷贝构造,即swap函数的交换只发生在函数体内部,无法传出)

4.拓展与思考

  • 本题限定的输入条件是“不含重复元素”的数组,如果含重复元素呢?
    解决:加入判断是否需要交换的函数"judgeswap"
 bool judgeswap(vector<int> &a, int i, int j) {
    if(a[i]==a[j]&&i!=j)//不需要交换的条件:两个不同位置元素值相等
        return false;
    else
        return true;
}

再在主要全排列算法中加入该函数即可
更改后如下:

for (int i = head; i <= end; i++) {
        if (judgeswap(a, head, i)) {
            swap(a, head, i);
            perm(a, head + 1, end, n);
            swap(a, head, i);
        }
    }

这样的算法就可以避免在有重复元素的情况下出现多种相同情况重复输出的情况了。

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值