You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++中生成字符串的无重复所有组合?

C++生成字符串无重复组合的实现方案

嘿,我来帮你搞定这个问题!你要的其实是保持原字符串字符顺序的所有非空子集——毕竟你提到的"重复"是像"12"和"21"这种打乱顺序的情况,只要我们严格遵循原字符串的字符顺序生成组合,就能从根源避免这类重复。

下面给你两种实现方式,递归和迭代都有,你可以按需选择:

一、递归实现(完美匹配示例输出顺序)

递归的思路其实就是模拟"选或不选当前字符"的决策树,调整递归顺序就能完美贴合你要的输出顺序:

#include <iostream>
#include <vector>
#include <string>

// 递归核心函数:index是当前处理的字符索引,current是当前拼接的组合,result存最终结果
void generateCombinations(const std::string& s, int index, std::string current, std::vector<std::string>& result) {
    // 所有字符处理完毕,非空组合加入结果
    if (index == s.size()) {
        if (!current.empty()) {
            result.push_back(current);
        }
        return;
    }

    // 优先选择当前字符,保证生成的组合顺序和示例一致(先处理以当前字符开头的所有组合)
    current.push_back(s[index]);
    generateCombinations(s, index + 1, current, result);

    // 回溯:去掉当前字符,处理不选它的情况
    current.pop_back();
    generateCombinations(s, index + 1, current, result);
}

int main() {
    std::string input = "123";
    std::vector<std::string> combinations;
    generateCombinations(input, 0, "", combinations);

    // 按示例格式输出
    for (size_t i = 0; i < combinations.size(); ++i) {
        if (i != 0) std::cout << ",";
        std::cout << combinations[i];
    }
    std::cout << std::endl; // 输出:1,12,123,13,2,23,3

    return 0;
}

递归思路解释:

  • 每一步处理到第index个字符时,先把它加入当前组合,递归处理后面的字符——这样会生成所有以当前字符开头的组合(比如处理"1"时,会生成"1"、"12"、"123",然后回溯去掉"2"生成"13")。
  • 回溯后再处理"不选当前字符"的情况,继续递归后面的字符——比如去掉"1"后,处理"2"生成"2"、"23",再去掉"2"处理"3"生成"3"。
  • 这种顺序完全贴合你给出的示例输出,而且因为严格遵循原字符串的字符顺序,绝对不会出现"21"、"213"这类打乱顺序的重复组合。

二、迭代实现(无递归开销,灵活调整顺序)

如果你不想用递归,也可以用迭代的方式生成所有组合,只是默认顺序和示例不同,但内容完全正确:

#include <iostream>
#include <vector>
#include <string>

std::vector<std::string> generateCombinationsIterative(const std::string& s) {
    std::vector<std::string> result;
    // 初始加入空组合,作为扩展基础
    result.push_back("");

    // 遍历每个字符,用现有组合拼接生成新组合
    for (char c : s) {
        size_t currentSize = result.size();
        // 对每个已有的组合,拼接当前字符生成新组合并加入结果
        for (size_t i = 0; i < currentSize; ++i) {
            result.push_back(result[i] + c);
        }
    }

    // 移除初始的空组合,得到所有非空组合
    result.erase(result.begin());

    return result;
}

int main() {
    std::string input = "123";
    std::vector<std::string> combinations = generateCombinationsIterative(input);

    // 输出结果(默认顺序:1,2,12,3,13,23,123)
    for (size_t i = 0; i < combinations.size(); ++i) {
        if (i != 0) std::cout << ",";
        std::cout << combinations[i];
    }
    std::cout << std::endl;

    return 0;
}

迭代思路解释:

  • 从空组合开始,每加入一个新字符,就把它和现有所有组合拼接,生成新的组合。比如处理"1"时,生成"1";处理"2"时,用""+"2"生成"2","1"+"2"生成"12";处理"3"时,生成"3"、"13"、"23"、"123",最终得到所有组合。

关于你遇到的重复问题

你之前说自己的实现有重复,大概率是因为没有限制字符的相对顺序,比如允许了打乱原字符串顺序的排列(比如生成了"21")。而我们的两种方法都严格保证组合中的字符顺序和原字符串一致,从根源避免了这类重复。你提到的"结果树"其实就是递归的核心思路——每个节点对应一个字符的"选/不选"决策,遍历这棵树就能得到所有合法组合。

内容的提问来源于stack exchange,提问作者Nick Law

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:46:20