我可以停止执行其他递归树分支吗?

Can I stop other recursion tree branches from executing?

我得到了一个整数向量和一个总和,如果该总和可以从该向量中元素的任意组合生成,我需要 return 该组合。如果可能有不止一种这样的组合,我可以 return 任意一种。

例如,

sum = 20, vector = {6,25,8},我们可以将 8 6 6 打印为 8+6+6 = 20

sum = 10, vector = {4,6,7}, 我们可以将 6 4 打印为 6+4 = 10

sum = 15, vector = {8,4,5},我们可以将 5 5 5 打印为 5+5+5 = 15

问题:上面的最后两个例子工作正常,但第一个没有。原因是,如果您为第一个示例绘制递归树,那么根据我的代码,您会得到 flag 变量 true 因为在同一父节点下存在多个 targetSum = 0 的基本情况.因此,最后一个示例打印 8 6 6 8 6.

我的问题是,因为我只需要打印加起来等于 targetSum 的任何可能组合,我可以跳过递归树的其他分支吗?基本上,一旦我们遇到 targetSum = 0 的基本情况,我们就会上树并打印出序列 ?那可能吗 ? (我曾尝试为此目的使用 stackCount,但如果找到总和为 targetSum 的序列,它只会阻止根节点的右侧子节点执行。)如果没有,则请让我知道如何或修改此代码中的内容,以使其正常工作。

#include <iostream>
#include <vector>
#include <map>

using namespace std;

bool howSum(int &targetSum, vector<int> &elementVector, vector<int> &howSumVector, map<int, bool> &memo, int &stackCount) {
    stackCount++;
    if (memo.find(targetSum) != memo.end())
        return memo[targetSum];
    else if (targetSum == 0)
        return true;
    else if (targetSum < 0)
        return false;
    else {
        for (auto i : elementVector) {
            int remainder = targetSum - i;
            bool flag = howSum(remainder, elementVector, howSumVector, memo, stackCount);
            stackCount--;
            if (flag) {
                    howSumVector.push_back(i);
                    memo[targetSum] = true;
            } else if(memo.find(targetSum) == memo.end())
                memo[targetSum] = false;
            if(stackCount == 1 && !howSumVector.empty())
                return true;
        }
        return memo[targetSum];
    }
}

int main() {
    int stackCount = 0;
    int sum = 20; // test cases 20,10,15
    map<int, bool> memo;
    vector<int> elements = {6,25,8}; // test cases {6,25,8},{4,6,7},{8,4,5}
    vector<int> workingBench = {};
    howSum(sum, elements, workingBench, memo, stackCount);
    for (auto i : workingBench)
        cout << i << " ";
}

您需要在找到匹配时结束递归,在本例中是 flag == true.

if (flag) {
    howSumVector.push_back(i);
    memo[targetSum] = true;
    return true; // We found a match! Stop searching!
}

编辑:

您没有正确使用备忘录。由于您只需要一种可能的解决方案,因此无需跟踪某个组合是否有效。

您想要的是跟踪之前是否有相同的余数。如果这样做,您可以直接中止搜索。

如果目标是 20 并且您有一些数字组合可以让您得到 5 的余数,那么是什么数字组合让我们达到目标并不重要。

假设我们无法从 15 到达目标,那么如果我们以某种不同的数字组合再次到达 15,我们已经知道我们永远无法从 15 到达目标,所以我们可以中止搜索那里。

如果我们可以从 15 开始达到目标,我们已经找到了解决方案并且递归已经结束,所以我们也不关心那个结果。

这是一个修改后的完整示例。

#include <iostream>
#include <vector>
#include <set>

using namespace std;

bool howSum(int targetSum, const vector<int> &elementVector, vector<int> &howSumVector, set<int> &memo) {
    if (memo.find(targetSum) != memo.end()) {
        return false;
    }
    memo.insert(targetSum);

    if (targetSum == 0) {
        return true;
    } else if (targetSum < 0) {
        return false;
    } else {
        for (auto i : elementVector) {
            bool flag = howSum(targetSum - i, elementVector, howSumVector, memo);
            if (flag) {
                howSumVector.push_back(i);
                return true;
            }
        }
        return false;
    }
}

int main() {
    int sum = 20; //20,10,15
    set<int> memo;
    vector<int> elements = {6,25,8}; // {6,25,8},{4,6,7},{8,4,5}
    vector<int> workingBench = {};
    howSum(sum, elements, workingBench, memo);
    if (workingBench.empty())
        cout << "not possible";
    else
        for (auto i : workingBench)
            cout << i << " ";
}

其他一些注意事项。我改为按值传递 targetSum 。您永远不会修改它,因此通过引用传递是没有意义的。

我也将 elementVector 更改为由 const & 传递,因为我们不想修改它。这只是一个好习惯。

我的最终代码-

#include <iostream>
#include <vector>
#include <map>

using namespace std;

bool howSum(int &targetSum, vector<int> &elementVector, vector<int> &howSumVector, map<int, bool> &memo) {
    if (memo.find(targetSum) != memo.end())
        return memo[targetSum];
    else if (targetSum == 0)
        return true;
    else if (targetSum < 0)
        return false;
    else {
        for (auto i : elementVector) {
            int remainder = targetSum - i;
            bool flag = howSum(remainder, elementVector, howSumVector, memo);
            if (flag) {
                howSumVector.push_back(i);
                memo[targetSum] = true;
                return true;
            } else if (memo.find(targetSum) == memo.end()) // if targetSum is NOT in memo
                memo[targetSum] = false;
        }
        return false;
    }
}

int main() {
    int sum = 20; //20,10,15
    map<int, bool> memo;
    vector<int> elements = {6,25,8}; // {6,25,8},{4,6,7},{8,4,5}
    vector<int> workingBench = {};
    howSum(sum, elements, workingBench, memo);
    if (workingBench.empty())
        cout << "not possible";
    else
        for (auto i : workingBench)
            cout << i << " ";
}