Implementing an equals method recursively

折月煮酒 提交于 2019-12-13 08:56:23

问题


Basically, I need to compare two arrays and check if they have the same values in the same positions (recursively of course). I get an error with my current code: Array out of index exception:20

The code I have right now looks as follows:

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

回答1:


Leaving aside the question of whether recursion is the right solution (it really isn't, iteration here is trivial and will perform better), the problem is that the termination condition (iStart == iEnd) is not checked until after the recursive call.

Any recursive algorithm must a) check whether it is appropriate to continue recursing, and b) do the recursive call after that check. Failing to include the first step, or doing the steps out of order, will result in infinite recursion until an error is reached (StackOverflowError if nothing else happens first).

You do have a condition check before your recursive call, but it's for the method's overall purpose rather than for ending recursion. You also have a condition check for ending recursion, but it's done after the recursive call. The solution is to swap their order - take the if (iStart == iEnd) block and move it to before the if (first[iStart] == second[iStart]) block.




回答2:


You simply need to put you stop condition at the begin of you code. This will work if iStart is 0 at the beginning and iEnd is array length - 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;
}

If you want to use the array length as input for iEnd you just need to change the code a little

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

Since performance was mentioned a few times I will say a few things about it. The stack contains information about local variables and function calls. So each recursiv call will save these informations on the stack which will lead to a stackoverflow on huge inputs since the stack only has limited space. It is also slower in terms of execution due to more assembler commands in comparison to loops.

This can be avoided by using tail recursive functions. A tail recursive call means simply that your recursive call must be the last statement that is executed in your method. The compiler will translate this into a loop. This is faster and uses less space on the stack.

A tail recursive version of your equals method would look like this:

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



回答3:


Recursion is a powerful programming technique, but has some draw backs in the Java language. If a method in java calls itself recursively an excessive number of times before returning it will lead to a StackOverflowError. It this instance, comparing equality of two Array's is almost guaranteed to do so.

Other languages like Scala allow you to write recursive functions which are optimised for recursion (tail recursive) and execute in constant stack space.

That been said, you should think whether recursion is really the correct solution here. It neither optimises the solution, nor adds code clarity.

Note: If you just want to compare two Array's in Java, then java.util.Arrays already has you covered.



来源:https://stackoverflow.com/questions/36120004/implementing-an-equals-method-recursively

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!