在二维数组中查找字符串

时间:2016-07-19 05:50:42

标签: algorithm time-complexity

这是一个需要针对时间进行优化的面试问题。

假设你有一个二维数组,并且你有一个字符串说"亚马逊"在数组内,使得各个字符可以从左到右,从右到左,从上到下,从下到上呈现。

我将用例子解释:

char[][] a = {
            {B,B,A,B,B,N},
            {B,B,M,B,B,O},
            {B,B,A,B,B,Z},
            {N,O,Z,B,B,A},
            {B,B,B,B,B,M},
            {B,B,B,B,B,A}
    };

上面的Array有两个Amazon Strings。您需要返回此类字符串的数量。

6 个答案:

答案 0 :(得分:2)

我做了一个简单的bfs,每次字符串toFind的第一个字符(在你的情况下是AMAZON)匹配2D数组中的一个字符。 一个简单的访问2D数组用于在一次迭代中检查标记的字符:

public class FindStrings {

private static int count = 0;       // Final Count

public static void find(Character[][] a, String toFind) {

    int rows = a.length;
    int col = a[0].length;

    boolean[][] visited = new boolean[a.length][a[0].length];

    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < col; j++) {
            if (a[i][j] == toFind.charAt(0)) {
                findUtil(visited, a, i, j, 0, toFind, new StringBuilder(), rows - 1, col - 1,new ArrayList<String>());
                visited[i][j] = false;
            }
        }
    }

}

private static void findUtil(boolean[][] visited, Character[][] a, int i, int j, int index, String toFind, StringBuilder result, int R, int C,ArrayList<String> list) {

    result.append(a[i][j]);
    //This list just prints the entire Path
    list.add(i+"-"+j);
    if (index == toFind.length() - 1 && result.toString().equals(toFind)) {
        System.out.println(list.toString());
        count++;
        return;
    }
    visited[i][j] = true; // Just to mark the character so that one character is not visited twice for a string match
    int nextIndex = index + 1; //Next index of the String to be compared

    int nextR, nextC;

    //Down
    if (i + 1 >= 0 && j >= 0 && i + 1 <= R && j <= C && !visited[i + 1][j] && a[i + 1][j] == toFind.charAt(nextIndex)) {
        nextR = i + 1;
        nextC = j;
        findUtil(visited, a, nextR, nextC, nextIndex, toFind, new StringBuilder(result), R, C,new ArrayList<>(list));
        //Every time we are done with the next character in the 2D Array we mark it visited
        visited[nextR][nextC] = false;
    }
    //Right
    if (i >= 0 && j + 1 >= 0 && i <= R && j + 1 <= C && !visited[i][j + 1] && a[i][j + 1] == toFind.charAt(nextIndex)) {
        nextR = i;
        nextC = j + 1;
        findUtil(visited, a, nextR, nextC, nextIndex, toFind, new StringBuilder(result), R, C,new ArrayList<>(list));
        visited[nextR][nextC] = false;
    }
    //Left
    if (i >= 0 && j - 1 >= 0 && i <= R && j - 1 <= C && !visited[i][j - 1] && a[i][j - 1] == toFind.charAt(nextIndex)) {
        nextR = i;
        nextC = j - 1;
        findUtil(visited, a, nextR, nextC, nextIndex, toFind, new StringBuilder(result), R, C,new ArrayList<>(list));
        visited[nextR][nextC] = false;
    }
    //Up
    if (i - 1 >= 0 && j >= 0 && i - 1 <= R && j <= C && !visited[i - 1][j] && a[i - 1][j] == toFind.charAt(nextIndex)) {
        nextR = i - 1;
        nextC = j;
        findUtil(visited, a, nextR, nextC, nextIndex, toFind, new StringBuilder(result), R, C,new ArrayList<>(list));
        visited[nextR][nextC] = false;
    }


}

public static int getCount() {
    return count;
}

public static void main(String[] args) {

    Character[][] a = new Character[][]{
            {'B', 'B', 'A', 'B', 'B', 'N'},
            {'B', 'B', 'M', 'B', 'B', 'O'},
            {'B', 'B', 'A', 'B', 'B', 'Z'},
            {'B', 'O', 'Z', 'O', 'N', 'A'},
            {'B', 'B', 'O', 'Z', 'B', 'M'},
            {'B', 'B', 'N', 'A', 'M', 'A'}
    };

    String toFind = "AMAZON";

    find(a, toFind);
    System.out.println(getCount());

}

答案 1 :(得分:1)

您可以从具有“A”的矩阵的每个单元格运行BFS,并计算可以构建Amazon的方式。最后将它们全部添加。

边缘: 如果相邻(上,下,左,右)节点(单元)包含亚马逊的下一个字符,则该节点(单元)具有来自当前节点(单元)的有向边。 例如,具有“N”的所有相邻节点具有来自具有“O”的节点的有向边缘。

答案 2 :(得分:1)

你只举了一个例子。如果:

  • 所有&#39;填充物&#39;字符总是不在字符串中
  • 字符串始终完整且未拆分
  • 该字符串至少有一个非重复字母

然后你只需要计算那些不重复的字母中有多少。例如,使用&AMAZON&#39;,您只需计算多少&#39; Z&#39; (或者&#39; M&#39;或者&#39; O&#39;或者&#39; N&#39;)在数组中。

这不像路径寻找算法那么通用,但肯定更快。

答案 3 :(得分:1)

  1. 迭代矩阵= O(N ^ 2)
  2. 找到第一次出现的密钥[0]即&#39; A&#39;在亚马逊并将其存储在[i,j]
  3. 从矩阵[i,j]开始,尝试跟踪亚马逊&#39;使用所有四个方向

    一个。您可以使用BFS或DFS

    湾如果找到,将计数增加1

    ℃。如果没有找到,请继续

  4. 时间复杂度= O(N ^ 2 + N){使用DFS}

答案 4 :(得分:1)

制作一个三维表格,矩阵中的每个位置都指代一个表示字母表中每个字母的数组。从顶部,从左到右,从右到左,逐行执行两次迭代:如果字符串存在,您将遇到其第一个或最后一个字母(唯一可以遇到中间字母的方法是,如果您&#39;已经看过其连线比赛的第一部分或最后一部分了。汇总左右发现,但将下面元素的位置表示在表示下一个可能字符的索引处,该字符包含当前长度和方向。如果遇到表匹配,将其转换为完全匹配或另一部分匹配(每个此类字母+位置单元格可以保存多个匹配)。

答案 5 :(得分:0)

我编写了一个解决这个问题的java代码

但就时间复杂度而言,它是一种昂贵的解决方案

当我遍历2d阵列扫描时,A&#39;然后从那个元素我遍历4个方向扫描M然后A扫描等等

因此,如果我们假设阵列的1次扫描是n ^ 2,则最糟糕的情况 我们扫描的单词的长度是K

将是

O(N ^ 2 * K ^ 4)这里的4是我们要搜索的4个方向

这是完全运行的类

public class Treetest {


public static void main(String[] args) {
    char[][] a = {
            {'B', 'B', 'A', 'B', 'B', 'N'},
            {'B', 'B', 'M', 'B', 'B', 'O'},
            {'B', 'B', 'A', 'B', 'B', 'Z'},
            {'N', 'O', 'Z', 'A', 'M', 'A'},
            //{'N', 'O', 'Z', 'B', 'B', 'A'},
            {'B', 'B', 'B', 'B', 'B', 'M'},
            {'B', 'B', 'B', 'B', 'B', 'A'}
    };

    int vertical = 0;
    int horiz = 0;
    int solutioncount = 0;
    for (char[] horizantal : a) {

        for (char element : horizantal) {
            if (element == 'A') {
                if (findnextChar(horiz, vertical, "A", a))
                    solutioncount++;
            }
            horiz++;
        }
        horiz = 0;
        vertical++;
    }
    System.out.println("Solution Count is : " + solutioncount);
}

public static boolean findnextChar(int posx, int posy, String currentFind, char[][] a) {
    char nextchar = 0;
    boolean checkMatch = false;
    switch (currentFind) {
        case "A":
            nextchar = 'M';
            break;
        case "AM":
            nextchar = 'A';
            break;
        case "AMA":
            nextchar = 'Z';
            break;
        case "AMAZ":
            nextchar = 'O';
            break;
        case "AMAZO":
            nextchar = 'N';
            checkMatch = true;
            break;

    }
    String nextString = currentFind + String.valueOf(nextchar);
    if (posx - 1 >= 0 && a[posy][posx - 1] == nextchar) {
        if (checkMatch) {
            return true;
        }
        return findnextChar(posx - 1, posy, nextString, a);
    }
    if (posx + 1 <= a[0].length - 1 && a[posy][posx + 1] == nextchar) {
        if (checkMatch) {
            return true;
        }
        return findnextChar(posx + 1, posy, nextString, a);

    }
    if (posy - 1 >= 0 && a[posy - 1][posx] == nextchar) {
        if (checkMatch) {
            return true;
        }
        return findnextChar(posx, posy - 1, nextString, a);

    }
    if (posy + 1 <= a[0].length - 1 && a[posy + 1][posx] == nextchar) {
        if (checkMatch) {
            return true;
        }
        return findnextChar(posx, posy + 1, nextString, a);
    }
    return false;

}

}