【问题标题】:Divide et impera sum of the elements of an array bugDivide et impera 数组错误的元素的总和
【发布时间】:2020-01-16 14:21:09
【问题描述】:

我写了下面的函数来计算一个向量中所有元素的总和,使用的是divide et impera方法

int Sum(std::vector<int> v, int left, int right)
{
int mid = (left + right) / 2;

if (left >= right)
    return v[mid];
else
    return Sum(v, left, mid - 1) + Sum(v, mid + 1, right);
}

//in main:
vector <int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

cout << Sum(v, 0, v.size() - 1);

但是,在给定的示例中,它输出 37 而不是 55。我使用调试器检查了它,它似乎跳过了某些数字。我尝试将left &gt;= right 更改为left &gt; right,但它仍然给了我一个错误的答案(56),尽管我认为从逻辑上讲它应该是left =&gt; right

代码有什么问题?

【问题讨论】:

  • 下次,请将您的代码发布为minimal reproducible example,例如this example。您的代码缺少include 标头,我们不知道main 是否缺少其他相关内容。如果你让别人来填补这些空白,那么填写的代码可能与你正在编译和运行的代码不匹配。
  • Sum(v, left, mid - 1) + Sum(v, mid, right); 这适用于O(n^2),因为您复制向量,通过 const 引用传递它:int Sum(const std::vector&lt;int&gt;&amp; v, int left, int right)
  • 似乎是时候学习如何使用 调试器 在监控变量及其值的同时逐语句执行代码了。在纸上调试时记下笔记也很有用。

标签: c++ recursion divide-and-conquer


【解决方案1】:

主要问题:递归从两个子和中排除mid

次要问题:left&gt;right 可能会发生(尽管初始输入合理,最坏的情况是 left == right + 1)。在这种情况下,您要返回 0

也许

if ( left > right ) 
   return 0;
else
   return Sum(v, left, mid-1) + v[mid] + Sum(v, mid+1, right);

【讨论】:

    【解决方案2】:

    错误就在这里,

    return Sum(v, left, mid - 1) + Sum(v, mid + 1, right);
    

    您缺少添加v[mid]。所以,改变它,

    if (left >= right)
        return v[left]; // v[mid] also helps.
    
    return Sum(v, left, mid) + Sum(v, mid + 1, right);
    

    【讨论】:

    • 您究竟做了哪些更改,为什么该更改会解决问题?请解释,不要只显示鼓励cargo cult programming 的代码。也请刷新how to write good answers
    • return Sum(v, left, mid - 1)+ v[mid] + Sum(v, mid + 1, right); 这个返回70(太多了)。其他两个工作正常,谢谢。
    • 希望,现在答案可以了。
    【解决方案3】:

    Sum 应该是这样的:

    int Sum(const std::vector<int>& v, int left, int right)  // pass vector by const reference
    {
    int mid = (left + right) / 2;
    
    if (left == right)  // there's no need to check whether left > right
                        // if you call function with left <= right
        return v[mid];
    else
        return Sum(v, left, mid) + Sum(v, mid + 1, right);  // you have missed mid
    }
    

    在您的版本中,您还在递归期间复制向量,尝试像这样调用您的函数:

    std::vector<int> v(100'000, 1);  // digit separator comes since C++14
    Sum(v, 0, v.size() - 1); 
    

    你会看到需要多长时间

    【讨论】:

      猜你喜欢
      • 2013-03-17
      • 1970-01-01
      • 2016-04-10
      • 2020-03-27
      • 2021-08-07
      • 2015-09-20
      • 2017-07-02
      • 1970-01-01
      • 2017-12-06
      相关资源
      最近更新 更多