跳到主要内容
极客日志极客日志
首页博客AI提示词GitHub精选代理工具
搜索
|注册
博客列表
C++算法

全排列问题回溯解法(C++ 实现)

综述由AI生成介绍如何使用回溯算法解决全排列问题。给定不含重复数字的数组,返回所有可能的排列。通过递归遍历,使用 used 数组标记已选元素,path 记录当前路径,当路径长度等于数组长度时保存结果。时间复杂度 O(n*n!),空间复杂度 O(n)。提供了 C++ 代码实现及调试示例。

宁静发布于 2026/3/23更新于 2026/4/278.3K 浏览
全排列问题回溯解法(C++ 实现)

题目描述

给定一个不含重复数字的数组 nums,返回其所有可能的全排列。你可以按任意顺序返回答案。

输入输出样例

示例 1: 输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例 2: 输入:nums = [0,1] 输出:[[0,1],[1,0]]

示例 3: 输入:nums = [1] 输出:[[1]]

提示: 1 <= nums.length <= 6 -10 <= nums[i] <= 10 nums 中的所有整数互不相同

题解

解题思路

思路一(递归(回溯)):
  1. 这题需求全排列,这里我们可以想到数学上进行全排列的过程。假设求 [1,2,3] 的全排列。我们首先需在 [1,2,3] 中,选取一个元素放在第一个位置,再在剩余两个元素中选取一个元素放在第二个位置,再将剩余的一个元素放在最后一个位置。

通过递归树可以分析出,每层会确定一个元素的位置,从上到下的一条路径正好是一个排列。(在此过程中我们需要记录哪些元素已被选取)

  1. 具体思路如下: ① 定义一个 used 用来存储当前元素是否被使用。定义一个 path 来存储从上到下的一条路径(正好是一个排列)。定义一个 ans 来存储所有的路径。 ② 递归的每层确定一个元素的位置,且每层会列举所有未使用的元素。(每层挑选一个元素(未使用)存入 path 中,将使用的元素进行标记)。 ③ 当 path 中元素的个数到达全排列的要求时,则将 path 存入 ans 中,再进行回溯(回溯时需将相应的元素置为未使用)。

  2. 复杂度分析 ① 时间复杂度:O(n * n!),其中 n 是数组中的元素数量。其主要是递归调用的次数和将 path 复制到 ans 中的时间开销。递归调用消耗 n!(全排列的个数),每个全排列答案复制到 ans 中消耗 n 时间。 ② 空间复杂度:O(n),其中 n 是数组中的元素数量。递归 n 层(每层确定一个元素的位置)O(n)。path 存储从上到下的一条路径(正好是一个排列)O(n)。使用一个 used 数组存储元素是否被使用 O(n)。

代码实现

代码实现(思路一(递归(回溯))):
class Solution {
private:
    // 用于存放一种排列
    vector<int> path;
    // 用于存放所有全排列
    vector<vector<int>> res;
    // 运用回溯算法求解全排列问题
    void backtracking(vector<int>& nums, vector<bool>& used) {
        // 递归出口(当 path 达到一个排列的个数时,也就是到达叶子节点时,记录答案)
        if (path.size() == nums.size()) {
            res.emplace_back(path);
            return;
        }
        // 在每个位置枚举不用的元素
        for (int i = 0; i < nums.size(); i++) {
            // 如果当前元素已经被使用则跳过此元素
            if (used[i] == true) continue;
            // 若当前元素还未使用,则将其添加到一个排列中,标记已使用
            path.emplace_back(nums[i]);
            used[i] = true;
            // 再重复的添加元素,直到一个排列的个数满足条件
            backtracking(nums, used);
            // 将当前元素移除切换其他元素,移除后标记为未使用
            path.pop_back();
            used[i] = false;
        }
    }
public:
    vector<vector<int>> permute(vector<int>& nums) {
        // 标记元素是否被使用
        vector<bool> used(nums.size(), false);
        backtracking(nums, used);
        return res;
    }
};
以思路一为例进行调试
#include<iostream>
#include<vector>
using namespace std;

class Solution {
private:
    // 用于存放一种排列
    vector<int> path;
    // 用于存放所有全排列
    vector<vector<int>> res;
    // 运用回溯算法求解全排列问题
    void backtracking(vector<int>& nums, vector<bool>& used) {
        // 递归出口(当 path 达到一个排列的个数时,也就是到达叶子节点时,记录答案)
        if (path.size() == nums.size()) {
            res.emplace_back(path);
            return;
        }
        // 在每个位置枚举不用的元素
        for (int i = 0; i < nums.size(); i++) {
            // 如果当前元素已经被使用则跳过此元素
            if (used[i] == true) continue;
            // 若当前元素还未使用,则将其添加到一个排列中,标记已使用
            path.emplace_back(nums[i]);
            used[i] = true;
            // 再重复的添加元素,直到一个排列的个数满足条件
            backtracking(nums, used);
            // 将当前元素移除切换其他元素,移除后标记为未使用
            path.pop_back();
            used[i] = false;
        }
    }
public:
    vector<vector<int>> permute(vector<int>& nums) {
        // 记录元素是否被使用
        vector<bool> used(nums.size(), false);
        backtracking(nums, used);
        return res;
    }
};

int main() {
    vector<int> a = {1, 2, 3};
    // 对 a 中的元素进行全排列
    Solution s;
    vector<vector<int>> results = s.permute(a);
    // 输出全排列的结果
    for (auto& result : results) {
        cout << "[";
        for (auto& i : result) {
            cout << i << " ";
        }
        cout << "] ";
    }
    return 0;
}

目录

  1. 题目描述
  2. 输入输出样例
  3. 题解
  4. 解题思路
  5. 思路一(递归(回溯)):
  6. 代码实现
  7. 代码实现(思路一(递归(回溯))):
  8. 以思路一为例进行调试
  • 💰 8折买阿里云服务器限时8折了解详情
  • GPT-5.5 超高智商模型1元抵1刀ChatGPT中转购买
  • 代充Chatgpt Plus/pro 帐号了解详情
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 开源无人机开发平台:基于 ESP32 的从零构建与自主飞行实践
  • MCP 实战:将 Figma 设计稿自动转换为前端代码
  • 二十届三中全会关于大规模设备更新措施深度解读
  • 基于 ONNX Runtime 的 YOLOv8 高性能 C++ 推理实现
  • ToClaw:基于 OpenClaw 的云端 AI 自动化助手评测
  • C++ Lambda 表达式详解:语法、捕获与底层原理
  • AI 产品难点解析:从 API 调用到工程化落地
  • DeepSeek 深度使用指南:提示词工程与本地知识库搭建
  • SpringBoot 配置文件核心用法:Properties 与 YAML
  • 毕业设计成绩管理系统:SpringBoot 后端+Vue 前端+MySQL
  • Generative Agents:交互式人类行为模拟研究
  • LTX-2.3 开源模型解析:音视频同步生成技术详解
  • 家庭 AI 助手(三):QQ 机器人接入 OpenClaw
  • Stable Diffusion WebUI终极指南:7步快速掌握AI图像生成
  • Llama-2-7B 昇腾 NPU 性能测评与部署实践指南
  • ES6 扩展运算符(...)在对象与数组中的实战用法
  • 分库分表无法解决无限扩容?聊聊单元化架构
  • 宇树 G1 机器人开发入门:有线与无线连接配置指南
  • Python 2.7 pip 9.0.1 安装与实战指南
  • 基于 Leaflet-Trackplayer 的 WebGIS 高速轨迹可视化实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online