我想以递归方式找到数组中最大元素的索引。函数的声明可以是这样的:
int maxIndex(const int *p, int size)
我正在研究递归,我看到了一些例子,比如递归地查找max数组元素。这很简单:
int maxInt( const int * p, int size)
{
if(size == 1)
return *p;
int max = maxInt(p + 1, size -1 );
if(max > *p)
return max;
else
return p[0];
}
我问自己,如何找到包含数组最大元素的索引。 我甚至不确定它是否有可能。你觉得怎么样?
答案 0 :(得分:5)
绝对有可能:您需要做的就是修改代码以返回指向max int的指针,然后从C中的maxInt
的返回值中减去初始指针,或者使用{{3}在C ++中。
const int* maxInt( const int * p, int size) {
if(size == 1)
return p;
int *maxPtr = maxInt(p + 1, size -1 );
if(*maxPtr > *p)
return maxPtr;
else
return p;
}
在C:
int index = maxInt(array, size) - array;
在C ++中:
ptrdiff_t index = std::distance(maxInt(array, size), array);
注意:使用递归解决此问题只应被视为学习练习的一部分,因为非常有可能溢出堆栈。这同样适用于任何其他可能具有大量递归调用且无尾调用优化的问题。
答案 1 :(得分:2)
让我们提出一个额外的问题。这里递归的主要问题是什么?主要问题是你最终会调用maxInt,因为你有元素。这将在同一时间发生,即调用堆栈将如下所示:
maxInt
maxInt
maxInt
...
鉴于调用堆栈限制在现代系统上的几百个调用(甚至可能更少),这个解决方案并不实用。但是,我们可以使它更实用吗?是的,我们可以 - 如果我们将当前递归转换为称为tail recursion
的东西 - 也就是说,当递归调用发生在函数的最末端时 - 我们可以使用所谓的尾部 - call optimization',它确保递归实际上不会调用函数,但行为类似于循环,并最终获得循环的灵活性和性能。就像我说的那样,关键是要确保最后调用该函数。以下是我们如何做到这一点:
int maxInt( const int * p, int size, int curr_max)
{
curr_max = (curr_max > *p) ? curr_max : *p;
if(size == 1)
return curr_max;
return maxInt(p + 1, size -1, curr_max);
}
如果你研究为这个函数生成的汇编语言是O1之上的任何优化,你会看到那里没有递归函数调用,而是有一个循环。
此解决方案可以与dasblinkenlight中的解决方案结合使用,为OP的家庭作业提供解决方案。
答案 2 :(得分:0)
这是您想要的功能标题所需的内容。从maxInt
返回的索引需要在每个递归级别进行调整,我使用+ 1
部分进行调整。
int maxInt(const int* p, int size)
{
if (size == 1)
{
return 0;
}
int max = maxInt(p + 1, size - 1) + 1;
return p[max] > *p ? max : 0;
}
请记住,每次问题中的代码返回时,它都会返回指向的值,而不是数组中的索引(*p
和p[0]
)。
答案 3 :(得分:-1)
to find the first index of a number....if same element are occurring multiple times example [9,8,10,8] and we have to find the first index of element 8.
int firstIndex(int input[], int size, int x) {
if(size==0)
{
return -1;
}
if(input[0]==x)
{
return 0 ;
}
int ans = firstIndex(input+1,size-1,x);
if(ans==-1)
{
return -1;
}else if(ans!=-1)
{
return ans+1;
}
}