递归地实现equals方法

时间:2016-03-20 21:47:41

标签: 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),iEnd))
        {
            return true;
        }
    }
    if (iStart == iEnd){
        return first[iEnd] == second[iEnd];
    }
    return false;
}

3 个答案:

答案 0 :(得分:1)

你只需要在代码的开头给你停止条件。如果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;
}

由于提到了几次表演,我会说几件事情。 堆栈包含有关局部变量和函数调用的信息。因此,每次递归调用都会在堆栈上保存这些信息,这将导致大量输入的堆栈溢出,因为堆栈只有有限的空间。由于与循环相比更多的汇编程序命令,它在执行方面也更慢。

使用尾递归函数可以避免这种情况。 尾递归调用意味着您的递归调用必须是您的方法中执行的最后一个语句。编译器会将其转换为循环。这样更快,并且在堆栈上占用更少的空间。

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);
        }
    }
}

答案 1 :(得分:0)

不考虑递归是否是正确的解决方案的问题(实际上并非如此,这里的迭代是微不足道的并且会表现得更好),问题是终止条件(iStart == iEnd)直到后才检查递归电话。

任何递归算法必须a)检查是否适合继续递归,以及b)在检查之后执行递归调用。如果没有包含第一步,或者不按顺序执行这些步骤,将导致无限递归,直到达到错误为止(StackOverflowError如果没有其他事先发生)。

在递归调用之前,您确实需要进行条件检查,但它是针对方法的总体目的而不是结束递归。您还有一个结束递归的条件检查,但它是在递归调用之后完成的。解决方案是交换他们的订单 - 获取if (iStart == iEnd)块并将其移至if (first[iStart] == second[iStart])块之前。

答案 2 :(得分:0)

递归是一种强大的编程技术,但在Java语言中有一些缺点。如果java中的方法在返回之前递归调用自身的次数过多会导致StackOverflowError。在这个例子中,比较两个Array的相等性几乎可以保证这样做。

Scala等其他语言允许您编写针对递归优化的递归函数(尾递归)并在常量堆栈空间中执行。

话虽如此,你应该考虑递归是否真的是正确的解决方案。它既没有优化解决方案,也没有增加代码清晰度。

注意:如果您只想比较Java中的两个数组,那么java.util.Arrays已经为您提供了保障。