此递归函数有什么作用?那么运行时的复杂性是什么?

时间:2020-06-09 23:29:57

标签: c++ recursion

我对以下代码感到困惑。到目前为止,我认为它将返回具有n个元素的数组中的最小整数。但是,递归如何工作?而且,此函数的运行时复杂度是多少?

int fun(int arr[], int n)
{
    int x;
    if (n == 1)
        return arr[0];
    else
        x = fun(arr, n - 1);

    if (x <= arr[n - 1])
        return x;
    else
        return arr[n - 1];
}

1 个答案:

答案 0 :(得分:2)

这确实是一个看起来很奇怪的函数,但是我们可以将其转换为更熟悉的形式,更经典的递归函数。

首先让我们重命名。 n显然是数组的长度,因此我们将n重命名为size。您假设fun在数组中找到最小值,因此让我们从这个假设开始,并重命名函数fun。最后,我们将看看该假设是否正确。

由于在then的{​​{1}}分支上,我们有一个if,我们可以抛弃return。然后将else声明移至首次使用的位置:

x

现在,我们清楚地看到了递归结束条件:int arr_min(int* arr, int size) { if (size == 1) return arr[0]; int x = arr_min(arr, size - 1); if (x <= arr[size - 1]) return x; else return arr[size - 1]; } ,在这种情况下,我们只返回数组的唯一元素。

接下来,让我们集中讨论n==1。我们可以看到这里的函数返回的是if/elsex之间的最小值,所以让我们这样写:

arr[n-1]

由于现在我们只读一次int arr_min(int* arr, int size) { if (size == 1) return arr[0]; int x = arr_min(arr, size - 1); return std::min(x, arr[size - 1]); } ,所以可以摆脱这个名字不好的变量:

x

这与您拥有的功能等效,但是具有更“经典”的递归形式。现在更容易看到函数确实返回了数组的最小元素:

非空数组的最小元素为:

  • 如果数组的大小为1:第一个也是唯一的元素
  • else:介于以下之间的最小值:
    • 最后一个元素和
    • 不包含最后一个元素的子数组的最小元素

现在也很容易看到时间复杂度。我把它留给你解决。


注意:现在应该很明显,该函数仅针对具有至少一个元素的数组定义。


作为奖励,我想用现代C ++重写此函数:

int arr_min(int* arr, int size)
{
    if (size == 1)
        return arr[0];

    return std::min(arr_min(arr, size - 1), arr[size - 1]);
}

在您附近的未来标准中:

constexpr int arr_min(std::span<const int> arr)
{
    if (arr.size() == 1)
        return arr.front();

    auto head = arr.first(arr.size() - 1);
    return std::min(arr_min(head), arr.back());
}