【问题标题】:Can I stop other recursion tree branches from executing?我可以停止执行其他递归树分支吗?
【发布时间】:2021-03-26 05:46:58
【问题描述】:

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

例如,

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 << " ";
}

【问题讨论】:

    标签: c++ recursion dynamic-programming


    【解决方案1】:

    您需要在找到匹配项时结束递归,在本例中为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 &amp; 传递,因为我们不想修改它。这只是一个好习惯。

    【讨论】:

    • 有趣,我也不需要再跟踪堆栈数了。
    • @DivyanshuVarma 我做了一些修改,以解决您使用 memo 和其他一些细节的问题。
    • "您没有正确使用memo。"对于这个确切的问题陈述,我同意你的这个修改后的解决方案简单而优雅。然而,在这个问题陈述之后,我的下一个任务是找到可能导致targetSum 的最小可能组合。所以可能我没有清楚地考虑这个问题陈述,而是考虑下一个!
    • "我改为通过值传递targetSum。你永远不会修改它,所以通过引用传递是没有意义的。"这是否意味着一遍又一遍地复制该值(不必要的时间+内存消耗)?
    • "我还把elementVector改成const &amp;传递,因为我们不想修改它。这只是一个好习惯。"是的,我同意,我现在会处理的。
    【解决方案2】:

    我的最终代码 -

    #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 << " ";
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-04
      • 2013-09-06
      • 2020-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多