栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

乱序全排列 简单回溯算法详解 [C++]

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

乱序全排列 简单回溯算法详解 [C++]

乱序全排列 简单回溯算法

目录
  • 乱序全排列 简单回溯算法
    • 力扣46 例题
    • 题解
    • 解释①
    • 尾言

力扣46 例题

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列

例:

输入:[1,3,4]

返回:[[1,3,4],[1,4,3],[3,1,4],[3,4,1],[4,1,3],[4,3,1]]

题解

了解了基本的全排列问题以后(见顺序全排列),了解了基本的回溯算法的思路,那么这道题有了一种新的回溯的思路;

同样的是三个数字,给定了一个数组nums[],但是数组里面的数字并不按照顺序排列,而是任意的三个数字;

基本思路不变,但是我们这次用一个新的思路;

例如[1,2,3],绑定第一个数字1之后,我们只需要交换nums[1]和nums[2]的顺序,就可以得到一个新的数列,也就是[1,3,2],同样的思路,绑定了2以后,因为2是nums[1],所以我们只需要交换nums[0]和nums[2]的顺序,就可以的到一个新的序列[2,1,3]和[2,3,1],交换顺序就等价于之前讲过的使用数据,交换回来就相当于重置数据;

那么根据上面的思路,就可以写出代码:

#include 
#include 
using namespace std;
void backk(vector >& res,vector& output,int first,int len){
    if(first == len){    // 出口 如果已经交换到最后一个了 就可以输出
        res.push_back(output);  // output加入到res容器中
        return ;
    }
    for(int i = first;i < len;i++){      
        swap(output[i],output[first]);  // 绑定第一个数字之后,进入循环开始交换另外两个数
        backk(res,output,first + 1,len);  // 进入递归
        swap(output[i],output[first]);  // 交换完成后,再次交换以重置数据,也就是回溯中的退回
    }
}

int main(){
    vector nums;
    vector > res;
    int n;
    int num;
    cin >> n;
    for(int i = 0;i < n;i++){  // 依次输入准备全排列的数字
        cin >> num;
        nums.push_back(num);       
    }
    backk(res,nums,0,(int)nums.size());
    for(int i = 0;i < res.size();i++){    // 输出二维容器
        for(int j = 0;j< res[i].size();j++){
            cout << res[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}


解释①

加入数据的时候使用 push_back()需要先构造临时对象,再将这个对象拷贝到容器的末尾,而emplace_back()则直接在容器的末尾构造对象,这样就省去了拷贝的过程。


尾言

感谢您的阅读!
如果文章有错误请留言指出,谢谢!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/876377.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号