给定正整数S与n,输出和为S的n元降序不同子集
解决生成固定长度、和为指定值的降序整数组合问题
看起来你正在尝试实现一个函数,生成所有长度为n且元素和为S的非递增整数组合(也就是你说的不同子集,这里其实是组合,因为不考虑顺序,只保留降序形式避免重复)。先帮你梳理核心逻辑,然后修正你的代码~
问题核心明确
我们需要生成的组合必须满足三个条件:
- 每个组合的长度恰好是
n - 所有元素的和等于
S - 组合是非递增排列(降序),确保不会出现重复组合(比如
4+2+1和2+4+1视为同一个,只保留前者)
比如你举的例子:S=7,n=3,输出的四个组合就是符合要求的所有可能。
现有代码问题分析
你当前的函数partitions(int X, int Y)参数命名模糊(推测X是和S,Y是长度n),且终止条件if (X <= 1 && X <= X - Y + 1)逻辑不通,递归部分的min(X - 1, Y)也不对——Y是长度,不是元素的最大值限制,这里应该限制当前元素的最大值,才能保证生成的组合是非递增的。
修正后的完整代码
#include <vector> #include <algorithm> #include <iostream> using namespace std; // 辅助递归函数:remaining_sum=剩余需凑的和,remaining_len=剩余需的元素个数,max_num=当前元素允许的最大值(保证非递增) void helper(int remaining_sum, int remaining_len, int max_num, vector<int>& current, vector<vector<int>>& result) { // 终止条件:只剩一个元素,直接加入当前组合 if (remaining_len == 1) { if (remaining_sum >= 1 && remaining_sum <= max_num) { current.push_back(remaining_sum); result.push_back(current); current.pop_back(); // 回溯,清理当前组合 } return; } // 当前元素的最大值:不能超过max_num,同时不能超过remaining_sum - (remaining_len-1)(剩下的元素至少每个是1) int upper = min(max_num, remaining_sum - (remaining_len - 1)); // 从大到小遍历,保证组合非递增 for (int y = upper; y >= 1; --y) { current.push_back(y); // 递归处理剩余的和、长度,下一个元素的最大值不能超过当前元素y helper(remaining_sum - y, remaining_len - 1, y, current, result); current.pop_back(); // 回溯,尝试下一个可能的元素 } } vector<vector<int>> partitions(int S, int n) { vector<vector<int>> result; vector<int> current; // 只有当S >=n时才有解(n个元素最小和为n,每个元素至少1) if (S >= n) { // 初始调用:第一个元素的最大值为S - (n-1),保证剩下n-1个元素至少能取1 helper(S, n, S - (n - 1), current, result); } return result; } // 按要求格式打印结果 void printResult(const vector<vector<int>>& res) { for (size_t i = 0; i < res.size(); ++i) { const auto& combo = res[i]; for (size_t j = 0; j < combo.size(); ++j) { if (j > 0) cout << " + "; cout << combo[j]; } if (i != res.size() - 1) cout << " "; } cout << endl; } // 示例调用 int main() { int S = 7, n = 3; auto res = partitions(S, n); printResult(res); // 输出:5 + 1 + 1 4 + 2 + 1 3 + 3 + 1 3 + 2 + 2 return 0; }
代码逻辑解释
辅助递归函数
helper:- 用
max_num限制当前元素的最大值,确保后续元素不会超过当前元素,从而维持非递增顺序,彻底避免重复组合。 - 回溯机制:每次加入当前元素后递归,递归完成后移除该元素,尝试下一个可能的取值。
- 用
终止条件处理:当只剩1个元素时,只要该元素在合法范围内(1到
max_num),就将其加入当前组合并存入结果。主函数
partitions:先判断S >=n(如果S小于n,n个元素的最小和都达不到S,直接返回空结果),再启动递归生成组合。打印函数
printResult:严格按照你要求的格式输出,组合之间用空格分隔,元素之间用+连接。
测试验证
当S=7,n=3时,运行代码会输出你期望的结果:5 + 1 + 1 4 + 2 + 1 3 + 3 + 1 3 + 2 + 2,完全符合要求。
内容的提问来源于stack exchange,提问作者Karl
相关产品推荐
相关产品推荐

