我正在推广另一个有类似递归调用的问题。在我的例子中,使用的变量是字符串,所以我不能简单地通过值来避免循环中递归调用之前和之后的代码。有没有办法把它变成迭代循环?请假设无法更改循环中递归调用之前和之后的代码以使此特定实例有效。
此代码测试以查看来自nums的任何int组合的总和是否加起来为零。 index的原始值为0,max是我想在任何给定解决方案中添加的最大数字。
为了进一步澄清,数字可以重复,所以我不能只尝试所有可能的组合,因为有无数的。
void findSolution(const vector<int>& nums, vector<int>& my_list, int& mySum,
int index, const int max)
{
if(mySum == 0) {
/* print my_list and exit(0) */
}
if(index < max) {
for(int i = 0; i < nums.size(); ++i) {
my_list.push_back(nums[i]);
mySum += nums[i];
findSolution(nums, my_list, mySum, index+1, max);
mySum -= nums[i];
my_list.pop_back();
}
}
}
答案 0 :(得分:0)
维护手动堆栈。
在您的情况下,递归调用的唯一独立状态是I的值和index的值。索引只是递归调用深度。
创建一个int的std向量,称为堆栈,将其保留为最大值。用while stack true替换循环。
在进入循环之前,在堆栈上按0。
将你的循环中的鳕鱼分成3个部分。 A B和C. A在递归调用之前,B是递归调用的,而C是在之后。包含在C中的是循环顶部的增量,它发生在原始代码中的C之后。
你在循环中做的第一件事是检查堆栈的顶部是大小还是更大。如果是这样,弹出堆栈,然后执行C并继续,除非堆栈为空,在这种情况下中断。
然后执行A.然后在堆栈上按0并在堆栈大小小于max时继续。然后执行C.您可以使用标志变量删除C代码重复。
请记住,堆栈的顶部替换了对I的任何引用。基本上我们正在替换一个递归调用,它会自动为我们创建一个堆栈,手动维护相同的堆栈,但只存储我们可以逃脱的绝对最小量。循环的开始作为递归调用的结束和循环的开始双重任务,所以我们可以取消goto。
尝试一下,在看完之后担心解释。关于标志变量的内容在代码到位后更有意义。