C++实现:将整数分拆为恰好k个不同整数的存储问题
整数分拆为恰好k个互不相同整数的递归实现(存储到vector<vector>)
嘿,我明白你现在的需求——要把整数拆成恰好k个互不相同的整数,而且得把结果存到vector<vector<int>>里,不是只打印出来对吧?递归方案其实完全能搞定这个,关键是要在递归过程中维护当前的分拆路径,并且用剪枝来提升效率,避免不必要的递归调用。
我直接给你写一个完整的实现,结构就是你想要的Partition()递归函数加Partition_main()主调用函数:
#include <vector> using namespace std; // 递归核心函数:负责生成符合条件的分拆 void Partition(int n, int remaining_k, int start_num, vector<int>& current_path, vector<vector<int>>& result) { // 终止条件:已经选够了k个数 if (remaining_k == 0) { // 检查当前路径的和是否等于目标n int sum = 0; for (int num : current_path) sum += num; if (sum == n) { result.push_back(current_path); } return; } // 剪枝优化:剩下的remaining_k个数至少是start_num, start_num+1, ..., start_num+remaining_k-1 // 它们的和是 remaining_k*start_num + (remaining_k*(remaining_k-1))/2 // 如果这个最小和已经大于n,就不用继续循环了 while (start_num * remaining_k + (remaining_k * (remaining_k - 1)) / 2 <= n) { current_path.push_back(start_num); // 递归调用:剩余需要选的数减1,下一个数从start_num+1开始(保证互不相同且递增,避免重复分拆) Partition(n - start_num, remaining_k - 1, start_num + 1, current_path, result); current_path.pop_back(); // 回溯,移除当前选的数,尝试下一个可能 start_num++; } } // 主调用函数:初始化容器并触发递归 vector<vector<int>> Partition_main(int n, int k) { vector<vector<int>> result; vector<int> current_path; // 第一个数从1开始(因为分拆的是正整数,如果你允许0的话可以改成0,但通常分拆是正整数) Partition(n, k, 1, current_path, result); return result; }
代码说明:
- 递归终止条件:当
remaining_k(还需要选的数的个数)为0时,检查当前路径的和是否等于目标n,如果是就把路径加入结果容器。 - 剪枝逻辑:循环的时候计算当前起始数开始的最小可能和,如果这个和已经超过n,直接终止循环,避免无效递归,大大提升效率。
- 互不相同的保证:每次递归调用的
start_num都是当前选的数+1,这样后续选的数一定比之前的大,既保证了互不相同,又避免了重复的分拆(比如不会同时出现[1,2,7]和[2,1,7])。 - 回溯操作:在递归返回后,把当前选的数从路径中移除,这样才能尝试下一个可能的数。
测试示例:
比如你提到的n=10,k=3的情况,调用Partition_main(10,3)会返回:
[[1,2,7], [1,3,6], [1,4,5], [2,3,5]]
完全符合你的要求,都是恰好3个互不相同的整数相加等于10。
这个方案的效率比单纯暴力递归高很多,因为剪枝操作跳过了大量不可能的情况,而且结果直接存储在vector<vector<int>>里,方便后续使用。
内容的提问来源于stack exchange,提问作者王韋翰
相关产品推荐
相关产品推荐

