我对以下代码感到困惑。到目前为止,我认为它将返回具有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];
}
答案 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/else
和x
之间的最小值,所以让我们这样写:
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
这与您拥有的功能等效,但是具有更“经典”的递归形式。现在更容易看到函数确实返回了数组的最小元素:
非空数组的最小元素为:
现在也很容易看到时间复杂度。我把它留给你解决。
注意:现在应该很明显,该函数仅针对具有至少一个元素的数组定义。
作为奖励,我想用现代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());
}