【问题标题】:C++ recursively find minimum value of arrayC ++递归查找数组的最小值
【发布时间】:2018-04-27 09:48:44
【问题描述】:

我有一个 c++ 编程类的任务,可以在不使用静态变量的情况下编写递归函数,原型如下: int findmin(const int a[], int n);

我的解决方案有效(适用于非常小的数组),但我认为 ~2^n 复杂度过高,可以改进。

在指定的标准内是否可以进行任何改进以提高效率?

int findmin(const int a[], int n)
{
    if(n == 0)
        return a[0];
    else
    {
        if(a[n-1] < findmin(a,(n-1)))
            return a[n-1];
      else
            return findmin(a,(n-1));
    }
}

【问题讨论】:

  • 存储findmin(a,(n-1)); 的结果而不是再次调用它会有所帮助。
  • 通过递归转到数组的最后一个索引。令最后一个元素为最小元素并返回它。在每次展开递归时,将当前索引元素与答案最小值进行比较,并在必要时进行更新。
  • @John3136 我很惊讶这有多大的不同,它现在似乎以线性复杂度运行。
  • 如果n代表大小,你的算法是错误的(a[0]n == 0时应该是无效的,否则你不检查a[n])。
  • 使用堆数据结构。 findMin()O(1)

标签: c++ recursion


【解决方案1】:

担心效率有点傻,因为有一种明显的、非递归的方式可以在 O(n) 中完成,一次通过。甚至还有一个 STL 算法 std::min_element。但是,这是一个愚蠢的任务。首先确保您的解决方案是正确的。当 n==0 时,a[0] 是否有效?一般这样的n表示数组的长度,而不是最低索引。

要从 O[n^2] 到 O[n],请确保每个元素只比较一次。这意味着不是每次都从数组的开头开始。

#include <algorithm>
#include <cassert>

int findmin(const int a[], int n)
{
    assert(n>0);
    if(n == 1)  // See heyah.
        return a[0];
    else
    {
        return std::min(a[0], findmin(a + 1, n - 1));
    }
}

在真正的 C++ 代码中,如果由于某种原因我们背负着老式的函数签名,我们会这样做:

int findmin(const int a[], int n) {
    if(n<=0) { throw std::length_error("findmin called on empty array");}
    return *std::min_element(a, a+n);
}

【讨论】:

  • 这是否也会创建一个副本O(n - 1) 次?
  • @codekaizer。它根本不创建副本。签名const int a[] 是 C 的保留。我们不再这样做了。 (C++ 新手甚至不应该知道它,但这是另一个咆哮。)数组声明a[]“衰减”到一个指针,int *a
  • @codekaizer - “Decay”听起来比“type rot”好。
  • @codekaizer - 任君挑选,但最终到这里:stackoverflow.com/questions/1461432/…
  • @BrijRajKishore - C++ 中的情况甚至比 Java 中的更好,前提是使用简单的方法。问题是,教师教学生编写 C 代码以使用 C++ 编译器进行编译。 C++ 中有很多特性,出于向后兼容性的原因,都保留在 C 中。
【解决方案2】:

您可以使用条件运算符?: 来摆脱一堆if else 语句,从而使函数更简洁。而不是调用findmin() 两次,您可以将返回值分配给语句内部的变量,这是此代码与原始代码相比的主要优势。

int findmin(const int a[], int n) {
   if (n == 0) // base case
      return a[0];

   return a[n] < (int min = findmin(a, n - 1)) ? a[n] : min;
}

这 (a[n] &lt; (int min = findmin(a, n - 1)) ? a[n] : min;) 也可以使用 if 语句来完成:

if (a[n] < (int min = findmin (a, n - 1))
     return a[n];
else
     return min;

编辑: 根据许多知名来源,这是 O(n) 时间。如果我们将每个元素与所有其他元素进行比较,则为 O (n^2)。

【讨论】:

  • @GRG 这是家庭作业问题或作业。写答案不是帮助的方式。请给他指路
  • @BrijRajKishore - 在某些情况下,编写答案可能会教会学生不要相信来自互联网的代码。 :-)
  • @BrijRajKishore 有时答案会被选为 +4,尽管它不正确且 O[n^2]。
  • @JiveDadson 告诉我这个算法是如何 O(n^2)
  • O(n^2) 并不意味着步数正好为 n^2。 (n^2-n)/2 是 O(n^2)。想办法。逐步执行算法并计数。把这个计数过程变成一个数学系列。玩得开心。我已经完成了。
猜你喜欢
  • 1970-01-01
  • 2016-05-07
  • 1970-01-01
  • 2011-08-01
  • 2021-12-08
  • 2016-06-10
  • 1970-01-01
  • 1970-01-01
  • 2016-01-20
相关资源
最近更新 更多