Java 递归实现equals方法
基本上,我需要比较两个数组,并检查它们在相同位置是否有相同的值(当然是递归的)。我的当前代码出错:数组超出索引异常:20 我现在拥有的代码如下所示:Java 递归实现equals方法,java,recursion,equals,Java,Recursion,Equals,基本上,我需要比较两个数组,并检查它们在相同位置是否有相同的值(当然是递归的)。我的当前代码出错:数组超出索引异常:20 我现在拥有的代码如下所示: private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd){ if (first[iStart] == second[iStart]){ if (equalsHelper(first,second,(iStart+1),i
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd){
if (first[iStart] == second[iStart]){
if (equalsHelper(first,second,(iStart+1),iEnd))
{
return true;
}
}
if (iStart == iEnd){
return first[iEnd] == second[iEnd];
}
return false;
}
撇开递归是否是正确的解决方案的问题不谈(其实不是,这里的迭代很简单,而且会执行得更好),问题是直到递归调用之后才检查终止条件(
iStart==iEnd
)
任何递归算法都必须a)检查是否适合继续递归,b)在检查之后执行递归调用。如果没有包含第一步,或者没有按顺序执行这些步骤,将导致无限递归,直到出现错误为止(StackOverflowerError
如果没有先发生任何其他情况)
在递归调用之前确实有一个条件检查,但它是为了方法的整体目的,而不是为了结束递归。您还有一个结束递归的条件检查,但它是在递归调用之后完成的。解决方案是交换它们的顺序——将
if(iStart==iEnd)
块移到if(first[iStart]==second[iStart])
块之前。递归是一种强大的编程技术,但在Java语言中有一些缺点。如果java中的方法在返回之前递归调用自身的次数过多,则会导致StackOverflower错误。在这种情况下,比较两个数组的相等性几乎可以保证做到这一点
Scala等其他语言允许您编写递归函数,这些函数针对递归(尾部递归)进行了优化,并在恒定的堆栈空间中执行
也就是说,您应该考虑递归是否真的是正确的解决方案。它既不优化解决方案,也不增加代码的清晰度
注意:如果您只想比较Java中的两个数组,那么
Java.util.Arrays
已经介绍过了。您只需要在代码开始时设置停止条件。如果iStart
开头为0,并且iEnd
为数组长度-1,则此操作有效
private boolean equalsHelper(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) { // you need to check this first
return first[iEnd] == second[iEnd];
}
if (first[iStart] == second[iStart]) {
if (equalsHelper(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
如果要使用数组长度作为iEnd
的输入,只需稍微更改代码即可
private boolean equalsHelper2(int[] first, int[] second, int iStart, int iEnd) {
if (iStart == iEnd) {
return true;
}
if (first[iStart] == second[iStart]) {
if (equalsHelper2(first, second, (iStart + 1), iEnd)) {
return true;
}
}
return false;
}
由于性能被提到了几次,我将对它说几句话。
堆栈包含有关局部变量和函数调用的信息。因此,每个recursiv调用都会将这些信息保存在堆栈上,这将导致在大量输入上出现堆栈溢出,因为堆栈只有有限的空间。与循环相比,它的执行速度也较慢,因为有更多的汇编命令
这可以通过使用尾部递归函数来避免。
尾部递归调用意味着递归调用必须是在方法中执行的最后一条语句。编译器将把它转换成一个循环。这会更快,并且在堆栈上使用更少的空间
equals方法的尾部递归版本如下所示:
private boolean equalsHelper2(int[] first, int[] second, int iStart, int iEnd)
{
if (iStart == iEnd)
{
return true;
}else{
if(first[iStart] != second[iStart])
{
return false;
} else
{
return equalsHelper2(first, second, iStart + 1, iEnd);
}
}
}
你应该在某个时候检查数组的
长度。这是家庭作业吗(你不能使用?我不认为这是递归的-当然。你把它复杂化了。为什么不先检查两个数组的长度是否不同。如果不是,它们就不相等-“当然”。如果是,就使用for循环,在每个索引上循环以比较相似的索引。如果你找到一个不相等的索引'不匹配-它们不相等。如果完成对所有元素的传递-它们相等。我不能。赋值需要递归解决方案。