最有效的算法,可水平,垂直或对角线检测四个以上相同字母的多个序列

时间:2019-07-05 15:31:07

标签: java string

我被分配了一项任务,以编写一种算法来检测给定的字符串数组是否包含水平,垂直或对角线的4个重复字母的多个序列。他们还问我最有效的方法。

一个输入示例将是这样的:

String[] input = {"ATGCGA","CAGTGC","TTATGT","AGAAGG","CCCCTA","TCACTG"};

但是你们可以在这里像桌子一样清楚地看到它:

A T G C G A
C A G T G C
T T A T G T
A G A A G G
C C C C T A
T C A C T G

此数组包含3个重复字母的序列:

对角线发现AAAA CCCC水平找到 垂直找到GGGG

因此,由于在此输入示例中找到了多个序列,因此输出应为true。

我有一个解决此问题的想法,但是我的主要问题是处理对角线,特别是使用一种有效的方法来解决这个问题,因为他们希望在高并发环境中使用此功能。

对于提供的任何帮助,我将不胜感激。可以,但不能写代码,但至少要有一些想法才能找到解决此问题的正确方法。

我已经很感激!

1 个答案:

答案 0 :(得分:1)

我认为您最好的选择是首先分析问题。

确定什么是对角线。在这种情况下,当遍历对角线时,行索引和列索引都增加1。

接下来,您必须执行一些规则。基于对角线长度4,有一个最大的行/列位置,任何对角线都可以从该位置开始。为了提高效率,您只应遍历可能导致匹配的索引。

为了直观地说明这一点,矩阵中所有这些X位置都可能是重复序列的开始:

X X X O O O
X X X O O O
X X X O O O
O O O O O O
O O O O O O
O O O O O O

因此,对于具有36个字符的6x6矩阵,我们最多只看9条长度为4的对角线。

现在我们只是满足长度要求的对角线,下一步就是简单地沿着对角线走,然后将每个下一个值与起始值进行比较。为了进一步提高效率,我们可以在对角线不再匹配起始字符后立即停止对其进行检查。

这是它可能在代码中播放的一种方式:

public static void main(String ... args) {
    // Find diagonal duplicates (AAAA) starting at (0, 0)
    String[] input = {"ATGCGA","CAGTGC","TTATGT","AGAAGG","CCCCTA","TCACTG"};
    findSequences(input);

    // Find diagonal duplicates (AAAA) starting at (2,2)
    String[] input2 = {"BTGCGA","CCGTGC","TTATGT","AGAAGG","CCCCAA","TCACTA"};
    findSequences(input2);

    // Find diagonal duplicates (ZZZZ) starting at (1,2)
    String[] input3 = {"BTGCGA","CCZTGC","TTCZGT","AGAAZG","CCCCAZ","TCACTA"};
    findSequences(input3);
}


private static void findSequences(String ...input) {
    // sought-after length of repeated characters
    int repeatLength = 4;

    // max row a diagonal of length 'repeatLength' could start at
    int maxStartRow = input.length - repeatLength;

    // max column a diagonal could start at... assumes all rows have same length.
    int maxStartColumn = input[0].length() - repeatLength;

    for (int i = 0; i <= maxStartRow; i++) {
        for (int j = 0; j <= maxStartColumn; j++) {
            boolean allMatch = true;
            char[] sequence = new char[repeatLength];
            // Capture the starting character
            sequence[0] = input[i].charAt(j);
            // Walk down the diagonal from the starting character
            // ceasing when the characters no longer match or we exceed the length
            for (int diagonalCounter = 1; diagonalCounter < repeatLength && allMatch; diagonalCounter++) {
                sequence[diagonalCounter]= input[i+diagonalCounter].charAt(j+diagonalCounter);
                allMatch &= (sequence[0] == sequence[diagonalCounter]);
            }
            if (allMatch) {
                System.out.println("Match " + String.valueOf(sequence) + " found, starting at (" + i + ", " + j + ")");
            }
        }
    }
}

打印:

Match AAAA found, starting at (0, 0)
Match AAAA found, starting at (2, 2)
Match ZZZZ found, starting at (1, 2)