Calculation of Hamming distance between two adjacency lists I have written a Java program to calculate the Hamming distance between two adjacency lists. The program calculates the Hamming distance correctly, but it takes a very long time, especially when dealing with bigger lists. Can anyone suggest a better way to optimize my program?

Below are the sample lists and the method that calculates Hamming distance:

Adjacency list for a:

0 =&gt; 0 1 2 
1 =&gt; 0 1 
2 =&gt; 


Adjacency list for b:

0 =&gt; 0 
1 =&gt; 0 1 2 
2 =&gt; 0 1 2


Hamming distance between Adjacency List A and B is: 6

public int hamming(ArrayList[] a, ArrayList[] b) {
    int distance = 0;
    for (int i2 = 0; i2 &lt; b.length; i2++) {
        for (int j2a = 0; j2a &lt; a[i2].size(); j2a++) {
            boolean found = false;
            for (int k = 0; k &lt; b[i2].size(); k++) {
                if ((int) a[i2].get(j2a) == (int) b[i2].get(k)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                distance++;
            }
        }
        for (int j2b = 0; j2b &lt; b[i2].size(); j2b++) {
            boolean found = false;
            for (int k = 0; k &lt; a[i2].size(); k++) {
                if ((int) b[i2].get(j2b) == (int) a[i2].get(k)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                distance++;
            }
        }
    }
    System.out.println("Hamming distance between Adjacency List  A and B is: " + distance + "\n");
    return distance;
}
First what you want is not the Hamming distance but the Levenshtein distance (the Hamming distance in fact assumes that the two strings (in this case lists) have the same size). 
Computing the Levenshtein distance is not trivial and to build an efficient algorithm you need to use the dynamic programming (otherwise you can come up with a recursive algorithm that is less efficient).

The approach is the following:
A list can be transformed in a second one by applying tree different operations to an element: insert, remove, modify.

With this in mind we design the algorithm as follow:
we keep a matrix M where 

M[i][j] = distance between the first i-th elms of the the first list and the first j-th elems of the second list.

Thus, the first row of the matrix represents the distance between an empty list and the second list if you consider only the first i-th elements. Thus it has to initialized as follow:

for i in range(len(l1)):
    M[0][i] = i


because we can always transform a list to the empty one by dropping all the elements (so i operations).

Similarly first column also  is initialized in the same way:

for i in range(len(l2)):
    M[i][0] = i


At this point to compute the distance between the first i elements of l1 and the first j elements of l2 we have to consider which is the operation that will transform l1 to l2 with fewer operations. So we take the minimum between 


the number of operations to transform l1[0:i-1] into l2[0:j] + 1 (the added 1 is the cost for this operation which is the deletion)
the number of operations that we had to perform to transform l1[0:i] into l2[0:j-1] + 1 (this represent the insertion operation)
and the number of operations to transform l1[0:i-1] into l2[0:j-1]. Summing 1 if l1[i] != l2[j] (we have to substitute te element), 0 otherwise.


This translated into formula is:

M[i][j] = min(M[i-1][j] + 1, M[i][j-1] + 1, M[i-1][j-1] + 1 if l1[i]==l2[j] else 0


Implementing everything in java is:

public static int editDistance(List&lt;String&gt; l1, List&lt;String&gt; l2)
{
    int[][] M = new int[l1.size()][l2.size()];
    for(int i = 0; i &lt; l2.size();i++)
        M[0][i] = i;
    for(int i = 0; i &lt; l1.size(); i++)
        M[i][0] = i;

    for(int i = 1; i &lt; l1.size(); i++)
    {
        for(int j = 1; j &lt; l2.size(); j++)
        {
            int substitute = 0;
            if(!l1.get(i).equals(l2.get(j)))
                substitute = 1;

            int minRemoveAdd = Math.min(M[i - 1][j] + 1, M[i][j - 1] + 1);
            M[i][j] = Math.min(minRemoveAdd, M[i-1][j-1] + substitute);
        }
    }
    return M[l1.size() - 1][l2.size() - 1];
}