找到最大的共同子序列

时间:2010-11-06 00:30:37

标签: java algorithm recursion

我有以下代码,由于我想弄清楚的某些原因,它无法正常工作:

public static int score(String gene1, String gene2){
    char[] a=new char[gene1.length()];
    char[] b=new char[gene2.length()];
    a=gene1.toCharArray();
    b=gene2.toCharArray();
    return score(a, b, 0,0);
}

private static int score(char[] a, char[] b, int i, int j){
    if(a[i]=='\0' || b[j]=='\0')
        return 0;
    else if (a[i]==b[j])
        return 1+score(a, b, i+1, j+1);
    else 
        return max(score(a, b,i+1, j),score(a, b, i, j+1));
}

private static int max (int a, int b){
    if (a<b) return b;
    else return a;
}

这是失败的地方:

assertEquals(2, GeneAnalysis.score("ACGT","AC")); 

我得到一个IndexOutofBoundsError

有什么想法吗?此外,在提供帮助时,请不要更改方法参数。他们应该是他们的方式。

3 个答案:

答案 0 :(得分:6)

部分原因似乎是C和Java之间的混淆....

if(a[i]=='\0' || b[j]=='\0')
        return 0;

C对字符串有空终止符,Java没有。而是要检查Java数组的结尾,您需要使用.length属性......类似于:

   if(i >= a.length || j >= b.length) 

根据评论进行修改。

真的,你应该就此问一个单独的问题......但这里有一个关于它是如何工作的刺。首先,你使用的是递归,这是一个棘手的概念。维基百科可能会帮助您了解递归的基础知识。

以下代码更接近于我将如何编写代码,其中的注释显示了事情发生的顺序:

public class Main
{
    public static void main(String[] args)
    {
        final int value;

        value = score("ACGT", "AC");
        System.out.println(value);
    }

    public static int score(final String gene1,
                            final String gene2)
    {
        final char[] a;
        final char[] b;
        final int    s;

        a = gene1.toCharArray();
        b = gene2.toCharArray();
        s = score(a, b, 0, 0);

        return (s);
    }

    private static int score(final char[] a,
                             final char[] b,
                             final int    idxA,
                             final int    idxB)
    {
        final int value;

        // for all calls: a.length == 4 and b.length == 2
        // first call:  idxA == 0 and idxB == 0 - false || false == false
        // second call: idxA == 1 and idxB == 1 - false || false == false
        // third call:  idxA == 2 and idxB == 2 - false || true  == true      
        if(idxA >= a.length || idxB >= b.length)
        {
            // third call: will return 0            
            value = 0;
        }
        // first call:  a[idxA] == A and b[idxB] == A - true
        // second call: a[idxB] == C and b[idxB] == C - true 
        else if(a[idxA] == b[idxB])
        {
            // this is recursion
            // first call:  1 + score(a, b, 1, 1)
            // second call: 1 + score(a, b, 2, 2)

            // after the third call the call stack starts unwinding
            // second call: 1 + 0 == 1
            // first call:  1 + 1 == 2
            value = 1 + score(a, b, idxA + 1, idxB + 1);
        }
        else
        {
            final int x;
            final int y;

            x = score(a, b, idxA + 1, idxB);
            y = score(a, b, idxB,     idxB + 1);
            value = max(x, y);
        }

        // third call:  0
        // second call: 1
        // first call:  2
        return (value);
    }

    // Can you use Math.max(int, int) instad?
    private static int max(final int x, final int y)
    {
        final int value;

        if(x < y)
        {
            value = y;
        }
        else
        {
            value = x;
        }

        return (value);
    }
}

答案 1 :(得分:3)

public static int score(String gene1, String gene2){
    char[] a=gene1.toCharArray();//assign it directly
    char[] b=gene2.toCharArray();
    return score(a, b, 0, 0);
}

private static int score(char[] a, char[] b, int i, int j) {
    //check for end using length, java doesn't use that nullbyte-stuff for it
    //this caused the failure
    if(i==a.length || j==b.length) {
        return 0;
    } else if (a[i]==b[j]) {
        return 1+score(a, b, i+1, j+1);
    } else {
        return max(score(a, b, i+1, j), score(a, b, i, j+1));
    }
}

private static int max (int a, int b){
    if (a<b) return b;
    return a;
}

答案 2 :(得分:0)

char[] a=new char[gene1.length()];
a=gene1.toCharArray();

嗯。您在第一行中分配的数组会发生什么变化?