javarecursionheap-memorydynamic-programmingedit-distance

Implementing edit distance method using recursion results in object heap error


    private static int editDistance(ArrayList<String> s1, ArrayList<String> s2) {
        if (s1.size()==0) {
            return s2.size();
        } 
        else if (s2.size()==0) {
            return s1.size();
        } 
        else {
            String temp1 = s1.remove(s1.size()-1);
            String temp2 = s2.remove(s2.size()-1);
            if (temp1.equals(temp2)) {
                return editDistance((ArrayList<String>)s1.clone(),(ArrayList<String>)s2.clone());
            } else {
                s1.add(temp1);
                int first = editDistance((ArrayList<String>)s1.clone(),(ArrayList<String>)s2.clone())+1;
                s2.add(temp2);
                s1.remove(s1.size()-1);
                int second = editDistance((ArrayList<String>)s1.clone(),(ArrayList<String>)s2.clone())+1;
                s2.remove(s2.size()-1);
                int third = editDistance((ArrayList<String>)s1.clone(),(ArrayList<String>)s2.clone())+1;
                if (first <= second && first <= third ) {
                    return first;
                } else if (second <= first && second <= third) {
                    return second;
                } else {
                    return third;
                }
            }
        }
    }

For example, the input can be ["div","table","tr","td","a"] and ["table","tr","td","a","strong"] and the corresponding output should be 2.

My problem is when either input list has a size too big, e.g., 40 strings in the list, the program will generate a can't reserve enough space for object heap error. The JVM parameters are -Xms512m -Xmx512m. Could my code need so much heap space? Or it is due to logical bugs in my code?

Edit: With or without cloning the list, this recursive approach does not seem to work either way. Could someone please help estimate the total heap memory it requires to work for me? I assume it would be shocking. Anyway, I guess I have to turn to the dynamic programming approach instead.


Solution

  • You clone() each ArrayList instance before each recursive call of your method. That essentially means that you get yet another copy of the whole list and its contents for each call - it can easily add-up to a very large amount of memory for large recursion depths.

    You should consider using List#sublist() instead of clone(), or even adding parameters to your method to pass down indexes towards a single set of initial List objects.