基于递归的全排列和全组合算法

全排列:

#include <vector>
#include <algorithm>
#include <iostream>

void permute(std::vector<int>& nums, int start, std::vector<std::vector<int>>& result) {
    // 如果到达数组末尾,将当前排列加入结果
    if (start == nums.size()) {
        result.push_back(nums);
        return;
    }
    
    // 对每个位置的数字进行交换尝试
    for (int i = start; i < nums.size(); ++i) {
        // 交换当前元素和起始元素
        std::swap(nums[start], nums[i]);
        // 递归处理后续元素
        permute(nums, start + 1, result);
        // 回溯,恢复原数组
        std::swap(nums[start], nums[i]);
    }
}

std::vector<std::vector<int>> getPermutations(std::vector<int>& nums) {
    std::vector<std::vector<int>> result;
    permute(nums, 0, result);
    return result;
}

int main() {
    std::vector<int> nums = {1, 2, 3};
    auto result = getPermutations(nums);
    for (const auto& perm : result) {
        for (int num : perm) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}

运行结果:

1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2

算法说明:

  1. 使用回溯法,通过递归交换数组元素生成所有可能的排列。
  2. permute函数在每次递归中:
  • 如果当前索引到达数组末尾,保存当前排列
  • 否则,遍历从当前索引到末尾的每个元素,交换并递归处理
  1. 每次递归后恢复数组状态(回溯)
  2. 主函数 getPermutations 初始化结果容器并调用递归函数

时间复杂度:O(n!),其中 n 是输入数组长度,因为需要生成所有可能的排列。
空间复杂度:O(n!),用于存储所有排列结果。

全组合:

代码:

#include <vector>
#include <iostream>

void combine(std::vector<int>& nums, int start, std::vector<int>& current, std::vector<std::vector<int>>& result) {
    // 将当前组合加入结果
    if (!current.empty()) {
        result.push_back(current);
    }
    
    // 从start开始选择后续元素
    for (int i = start; i < nums.size(); ++i) {
        // 选择当前元素
        current.push_back(nums[i]);
        // 递归处理后续元素
        combine(nums, i + 1, current, result);
        // 回溯,移除当前元素
        current.pop_back();
    }
}

std::vector<std::vector<int>> getCombinations(std::vector<int>& nums) {
    std::vector<std::vector<int>> result;
    std::vector<int> current;
    combine(nums, 0, current, result);
    return result;
}

int main() {
    std::vector<int> nums = {1, 2, 3};
    auto result = getCombinations(nums);
    for (const auto& comb : result) {
        for (int num : comb) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }
    return 0;
}

输出:

1 
1 2 
1 2 3 
1 3 
2 
2 3 
3 

算法说明:

  1. 使用回溯法,通过递归选择或不选择元素生成所有可能的组合。
  2. combine 函数在每次递归中:
  • 如果当前组合不为空,保存到结果
  • 从当前索引开始,依次选择每个元素加入组合
  • 递归处理后续元素
  • 回溯,移除当前元素继续尝试其他组合
  1. 主函数 getCombinations 初始化结果容器并调用递归函数

时间复杂度:O(2^n),其中 n 是输入数组长度,因为每个元素有选或不选两种状态。
空间复杂度:O(2^n),用于存储所有组合结果。

posted @ 2025-05-23 21:12  紫川Bin  阅读(42)  评论(0)    收藏  举报